1 апреля 2020 г. 19:09

Утечка памяти при динамическом выделении

Всем привет.
Такой вопрос, в классе есть приватный метод, в который передаются некоторые данные

QSGGeometryNode *NavRect::lineNode(QPoint beginPoint , QPoint endPoint, QColor colorLine, QSGGeometryNode *oldNode)
{
    auto material = new QSGFlatColorMaterial;
    material->setColor(colorLine);

    if(!oldNode)
    {
        auto pNode = new QSGGeometryNode;
        auto pLineGeometry=new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
        pLineGeometry->setLineWidth(1);
        pLineGeometry->setDrawingMode(GL_LINES);

        pLineGeometry->vertexDataAsPoint2D()[0].set(beginPoint.x(), beginPoint.y());
        pLineGeometry->vertexDataAsPoint2D()[1].set(endPoint.x(), endPoint.y());

        pNode->setGeometry(pLineGeometry);
        pNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial);
        pNode->setMaterial(material);

        return pNode;
    }
    else
    {
        oldNode->setMaterial(material);
    }

    return oldNode;
}

Как тут видите в нем аж 3 new, то есть один возвращается в метод класса для дальнейшей работы, а вот другие 2 нет.
Как правильно разабратся с ними чтоыб указатели не плавали после выхода из метода?
Если их сделать мемберами в данном классе это вроде не избавляет от проблемы?
Спасибо.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
8

Привет.

Здесь не надо ничего такого делать, память здесь будет очищаться за счёт этой строчки

pNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial);

То есть ты берёшь владение материалом и геометрией на pNode, а сама pNode должна будет уничтожаться дальше в дереве объектов OpenGL, попутно уничтожая материал и геометрию. QML всё это предусматривает.

Если по какой-то причине всё-таки происходит утечка памяти, то значит косяк где-то в логике метода updatePaintNode

Для проверки можно сделать для всех этих классов наследников и переопределить деструктор с выводом qDebug, как сделано в этой статье для QStandardItem . Это позволит убедиться, что удаление всё-таки происходит.

Оки спасибо, сейчас проверю.

  • 2 апреля 2020 г. 3:40

В общем все таки утечка есть, по причине логики метода где вызывается данная функция.
Вот так она выглядит

QSGNode *NavRect::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *updatePaintNodeData)
{
    Q_UNUSED(updatePaintNodeData)

    QColor foreground = Qt::white;
    QColor background = Qt::black;

    auto width = boundingRect().width();
    auto height = boundingRect().height();

    if(hasFocus())
    {
        background = Qt::white;
        foreground = Qt::black;
    }

    setProperty("foreground", foreground);
    setProperty("background", background);


    if(!oldNode)
    {
        //! complete creation of objects and attaching them to a node, background color
        m_pBackgroundNode = window()->createRectangleNode();
        m_pBackgroundNode->setRect(boundingRect());
        m_pBackgroundNode->setColor(background);

        //! draw lines
        m_pNodeLineOne = lineNode(QPoint(0, 0), QPoint(width, 0), foreground);
        m_pNodeLineTwo = lineNode(QPoint(width, 0), QPoint(width, height), foreground);
        m_pNodeLineThree = lineNode(QPoint(width, height), QPoint(0, height), foreground);
        m_pNodeLineFour = lineNode(QPoint(0, height), QPoint(0, 0), foreground);

        m_pBackgroundNode->appendChildNode(m_pNodeLineOne);
        m_pBackgroundNode->appendChildNode(m_pNodeLineTwo);
        m_pBackgroundNode->appendChildNode(m_pNodeLineThree);
        m_pBackgroundNode->appendChildNode(m_pNodeLineFour);

        return m_pBackgroundNode;
    }

    //! if a node exists, update the background
    m_pBackgroundNode->setColor(background);

    //! updating lines
    m_pNodeLineOne = lineNode(QPoint(0, 0), QPoint(width, 0), foreground, m_pNodeLineOne);
    m_pNodeLineTwo = lineNode(QPoint(width, 0), QPoint(width, height), foreground, m_pNodeLineTwo);
    m_pNodeLineThree = lineNode(QPoint(width, height), QPoint(0, height), foreground, m_pNodeLineThree);
    m_pNodeLineFour = lineNode(QPoint(0, height), QPoint(0, 0), foreground, m_pNodeLineFour);

    return oldNode;
}

То есть при первом входе создаюется обьект и вызывается lineNode для создания линий, а потом когда уже нода существует то мы снова заходим в метод и опять делаем new.
Так что вот с этим и проблема как раз.

Проблема в том, что если нода уже была создана, то ты заново пересоздаешь ноды, а не перерисовываешь. Посмотри как сделано в этой статье QML - Урок 032. Создаём Custom QuickItem из C++ с использованием средств OpenGL

Я не создаю там новые объекты, если oldNode существует, я перерисовываю ноду в уже существющих объектах. А ты просто создаешь каждый раз новые объекты m_pNodeLineOne, m_pNodeLineTwo, m_pNodeLineThree, m_pNodeLineFour если oldNode . Либо удаляй их, если они существуют и потом создавай новые, либо переопределяй некоторые свойства. Переопределение наверняка будет производительнее, чем создавать новые объекты.

В общем тебе нужен ещё один метод, который будет менять точки, то есть менять геометрию.

хотя, если вниметльно посмотреть на метод lineNode, то скорее всего проблема в том, что ты создаешь материал в начале метода. Старый скорее всего не удаляется, пока не была удалена нода, а просто заменяется, и остаётся висеть в памяти.

  • 3 апреля 2020 г. 11:52

В общем я просто сделал вторйо метод который простог обнавляет цвет и материал, вроде сделал правильно.
Но вот на эмбедеде есл ия быстро переключаюсь межуд обьектами они начали как бы мерцать, у меня предположение что я что то еще должен добавить в метод но не пойму что.

QSGGeometryNode *NavRect::nonExistLineNode(QPoint beginPoint , QPoint endPoint, QColor colorLine, QSGGeometryNode *oldNode)
{
    m_pMaterial = new QSGFlatColorMaterial;
    m_pMaterial->setColor(colorLine);

    if(!oldNode)
    {
        m_pGeometryNode = new QSGGeometryNode;
        m_pGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
        m_pGeometry->setLineWidth(1);
        m_pGeometry->setDrawingMode(GL_LINES);

        m_pGeometry->vertexDataAsPoint2D()[0].set(beginPoint.x(), beginPoint.y());
        m_pGeometry->vertexDataAsPoint2D()[1].set(endPoint.x(), endPoint.y());

        m_pGeometryNode->setGeometry(m_pGeometry);
        m_pGeometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial);
        m_pGeometryNode->setMaterial(m_pMaterial);

        return m_pGeometryNode;
    }
    else
    {
        oldNode->setMaterial(m_pMaterial);
    }

    return oldNode;
}

QSGGeometryNode *NavRect::existLineNode(QPoint beginPoint, QPoint endPoint, QColor colorLine, QSGGeometryNode *oldNode)
{
    m_pMaterial->setColor(colorLine);

    oldNode->setMaterial(m_pMaterial);

    return oldNode;
}

Само собою на компе этого незаметно.

Попробуй не переустанавливать материал, а просто менять цвет

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Как стать автором?

Внесите вклад в развитие сообщества EVILEG.

Узнайте, как стать автором сайта.

Изучить
Donate

Добрый день, Дорогие Пользователи !!!

Я Евгений Легоцкой, разработчик EVILEG. И это мой хобби-проект, который помогает учиться программированию другим программистам и разработчикам

Если сайт помог вам, и вы хотите также поддержать развитие сайта, то вы можете сделать пожертвование следующими способами

PayPalYandex.Money
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг Timeweb
s
3 июня 2020 г. 1:56
silo1995

C++ - Тест 003. Условия и циклы

  • Результат:35баллов,
  • Очки рейтинга-10
АП
2 июня 2020 г. 21:11
Алексей Пикенин

C++ - Тест 005. Структуры и Классы

  • Результат:75баллов,
  • Очки рейтинга2
2 июня 2020 г. 13:04
Даниил Чижевский

C++ - Тест 001. Первая программа и типы данных

  • Результат:86баллов,
  • Очки рейтинга6
Последние комментарии
МА
3 июня 2020 г. 11:40
Михаил А

Qt/C++ - Урок 050. Логирование событий Qt приложения в текстовый файл

Как только переношу в класс метод messageHandler, он подчеркнут ошибкой в конструкторе: qInstallMessageHandler(messageHandler); Сам метод в классе называется уже: void Customers::mess…
МА
3 июня 2020 г. 10:13
Михаил А

Qt/C++ - Урок 050. Логирование событий Qt приложения в текстовый файл

Вопрос- как перенести из файла .cpp // Умный указатель на файл логированияQScopedPointer<QFile> m_logFile;// Объявляение обработчикаvoid messageHandler(QtMsgType type, const QMessa…
3 июня 2020 г. 5:16
Евгений Легоцкой

Django - Урок 048. Как добавить статус онлайн на сайте

Добрый день. Конечно, нужно будет только шаблонный тег написать, который будет забирать всех пользователей онлайн, проверяя группу текущего пользователя. У меня пользователи онлайн на …
3 июня 2020 г. 4:43
Владислав Меленчук

Django - Урок 048. Как добавить статус онлайн на сайте

Доброго дня. А можно реализовать с помощью этой фичи вывод блок "Пользователи онлайн" и окрашивать взависимости от группы юзера? Как в скрине ниже. Screenshot_36.png
31 мая 2020 г. 8:15
IscanderChe

Как установить OpenCV на Qt под Windows

Добавлю от себя: на Windows 10 x64 с MinGW 7.3.0 в CMake надо установить флаг OPENCV_ENABLE_ALLOCATOR_STATS=OFF, тогда всё скомпилится нормально.
Сейчас обсуждают на форуме
f
3 июня 2020 г. 1:49
fryn3

Можно ли сделать в QML таблицу как в Excel?

edi-tableview - нашел пока такое выглядит коряво, посмотрим что можно сделать
2 июня 2020 г. 2:46
Евгений Легоцкой

Медиа файлы Google Firebase

Картинки можете попробовать сжимать через QPixmap, там есть возможность установки scaleFactor, через него можете устанавливать нужные параметры. А что касается конвертации видео, то лучше п…
2 июня 2020 г. 2:01
Евгений Легоцкой

Перехват обращения к локальным файлам QWebEngineView

В вашем случае вполне адекватное решение. Так сказать меньше зло. В противном случае пришлось бы очень много переписывать и перепиливать.
a
1 июня 2020 г. 10:26
alekseyttrv

SSL на Android

у меня стоит версия Qt 5.14.2. В настройках android поставил openssl из коробки, и этот прроект автоматически стянулся. Достаточно было только добавить в .pro-файл строку после этого и все …
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB