Welcome, Guest. Please login or register.
Did you miss your activation email?

Author Topic: Memory leak  (Read 3018 times)

Dunkan

  • Newbie
  • *
  • Posts: 9
    • View Profile
Memory leak
« on: February 03, 2020, 10:38:21 AM »
Добрый день!
Замечена утечка в файле https://github.com/fralx/LimeReport/blob/master/limereport/lrreportengine.cpp 1353-1356 строки.

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #1 on: February 03, 2020, 12:21:47 PM »
Добрый день!
Чем проверяли?

Dunkan

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Memory leak
« Reply #2 on: February 03, 2020, 12:54:06 PM »
Начинал с различных утилит по поиску утечек. Но в итоге пришлось искать вручную.

В конструктор TextItem добавил:

Code: [Select]
TextItem::TextItem( QObject *owner, QGraphicsItem *parent )
{
    listLeak.append( this );
    qDebug() << "create " << dynamic_cast<QObject *>( this ) << listLeak.size();
}

Где listLeak: static QList<QObject *> listLeak;

В деструктор:

Code: [Select]
TextItem::~TextItem()
{
    listLeak.removeOne( this );

    qDebug() << "delete" << dynamic_cast<QObject *>( this ) << listLeak.size();
}

Шло постоянное увеличение размеров listLeak, при каждом открытии отчета.

проверил так же в цикле, подтвердилось
Code: [Select]
for ( int i = 0; i < 100; i++ )
{
    PreviewReportWidget *wdg = m_report->createPreviewWidget(); // где m_report = new LimeReport::ReportEngine()
    delete wdg;
}

отчет довольно большой, около 70 объектов при каждом цикле терялось и чуть более 7мб оперативной памяти за все циклы.
Убрав комментарии с 1353-1355 строк:
Code: [Select]
//foreach(PageItemDesignIntf* page, m_renderingPages){
//    delete page;
//}

проблема была успешно решена. Объекты теряться перестали, утечка уменьшилась с 7мб до чуть менее 1мб, возможно где то еще есть проблема, пока не могу найти.

Сможете также проверить данную проблему? Возможно я что-то где-то упускаю?
« Last Edit: February 03, 2020, 01:12:40 PM by Dunkan »

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #3 on: February 03, 2020, 04:51:11 PM »
Все дело в том, что в лоб утечки в Qt детектировать не получается :(.
Qt имеет собственные механизмы выделения, кэширования и освобождения памяти.

Quote
//foreach(PageItemDesignIntf* page, m_renderingPages){
//    delete page;
//}
Удаляет отрендеренные страницы, которые хранятся в шаредпоинтере и в прямом удалении не нуждаются, более того это противопоказано :)
Если предположить, что страницы не удаляются вовсе, то на каждом запуске рендера было бы кратное увеличение потребления памяти.
Наиболее достоверным способом измерения выделенной и освобожденной памяти является
замер кол-ва выделенной памяти до создания ReportEngine и после его освобождения (И даже в этом случае Qt может прикопать у себя часть памяти и перераспределить её позже).

Dunkan

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Memory leak
« Reply #4 on: February 04, 2020, 07:27:09 AM »
Но как быть с тем что каждый вызов ReportEngine::createPreviewWidget() приводит к утечке объектов TextItem. Даже после удаления ReportEngine, часть созданных TextItem висят в памяти.

Простейший пример:

Code: [Select]
for ( int i = 0; i < 10; i ++ )
{
    TestMemoryLeak();
}

void TestMemoryLeak()
{
    QString path = "Путь до отчета";

    LimeReport::ReportEngine *limereport = new LimeReport::ReportEngine();

    limereport->loadFromFile( path );

    auto prev = limereport->createPreviewWidget();

    delete prev;
    delete limereport;
}
« Last Edit: February 04, 2020, 07:57:11 AM by Dunkan »

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #5 on: February 04, 2020, 09:18:30 AM »
Ок, проверю. 

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #6 on: February 04, 2020, 11:45:32 AM »
Вы оказались совершенно правы, спасибо :). Зависали шаблонные страницы. 
Исправил, запушил. 

Dunkan

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Memory leak
« Reply #7 on: February 04, 2020, 12:39:14 PM »
Огромное спасибо! Сейчас пока разбираюсь с еще одной возможной утечкой, хотя это скорее даже не утечка, а исключительная ситуация, вкратце опишу свою мысль:
Имеется функция
Code: [Select]
void ScriptEngineModel::updateModel(), в которой используется следующее выражение
Code: [Select]
m_rootNode->clear();. Но т.к. m_rootNode создается в модели, которая хранится в классе типа Singlton, то при удалении ReportEngine и PreviewReportWidget m_rootNode с дочерними узлами остается в памяти, до завершения приложения. Но также был замечен рост кол-ва ScriptEngineNode почти с каждым новым циклом, а это уже становится похожим на утечку, использовал тот же тест что и выше, и проверял подобным способом:

Code: [Select]
static int countScriptEngineNode = 0;

ScriptEngineNode::ScriptEngineNode( const QString &name, const QString &description, NodeType type, ScriptEngineNode *parent, const QIcon &icon )
    : m_name( name ), m_description( description ), m_icon( icon ), m_type( type ), m_parent( parent )
{
    qDebug() << "create ScriptEngineNode " << this << ++countScriptEngineNode;
}

ScriptEngineNode::~ScriptEngineNode()
{
    qDebug() << "delete ScriptEngineNode" << this << --countScriptEngineNode;

    for ( int i = 0; i < m_childs.count(); ++i )
    {
        delete m_childs[i];
    }
}
« Last Edit: February 04, 2020, 12:40:45 PM by Dunkan »

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #8 on: February 04, 2020, 12:45:51 PM »
Ок. Тоже поковыряю :)

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #9 on: February 04, 2020, 05:22:45 PM »
Поправил :) Пушнул :)

Dunkan

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Memory leak
« Reply #10 on: February 05, 2020, 08:28:24 AM »
Благодарю!
Заметил что в новом коммите в функции
Code: [Select]
bool ScriptEngineManager::addFunction(const QString& name,
                                              QScriptEngine::FunctionSignature function,
                                              const QString& category,
                                              const QString& description)

на строке 282 имеется вызов функции containsFunction, которая была удалена... а также обратите внимание на строку 291, там тоже идет ошибочка небольшая

Arin Alex

  • Developer
  • Administrator
  • Hero Member
  • *****
  • Posts: 992
    • View Profile
Re: Memory leak
« Reply #11 on: February 05, 2020, 10:22:26 AM »
Поправил, спасибо, что обратили моё внимание на этот косяк:)
QScriptEngine уже не использую вот и пропустил :)
 

Dunkan

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Memory leak
« Reply #12 on: February 05, 2020, 10:55:55 AM »
Супер! =)