Russian Qt Forum

Qt => Общие вопросы => Тема начата: Маус от Январь 12, 2013, 15:17



Название: QObject утечка памяти
Отправлено: Маус от Январь 12, 2013, 15:17
CMyBase myObject;
вызываем myObject->setMyItem(value);

в объекте идет цепочка вызовов уже распределенных (по памяти) объектов
и за 500-700 вызовов подряд наблюдаем большую утечку памяти (рост с 600 мб до 2 гб занятой прогой памяти) и после этого программа выбрасывает. Интересует также вообще вопросы как Qt 4.7 работает с памятью и почему так неэкономно её расходует.
Код
C++ (Qt)
class CMyBase : public QObject
{
Q_OBJECT
public:
CMyItem* MyItem;
bool setMyItem(QVariant value);
}
bool CMyBase::setMyItem(QVariant value)
{
return MyItem->setValue(value);
}
 
 
class CMyItem : public QObject
{
Q_OBJECT
public:
       QList<CMySubItem>* list;
       bool setValue(QVariant value);
}
bool CMyItem:: setValue(QVariant value)
{
list->at(555)->setValue(value);
return true;
}
 
class CMySubItem : public QObject
{
Q_OBJECT
public:
       QVariant myValue;
       bool setValue(QVariant value);
}
bool CMySubItem ::setValue(QVariant value)
{
myValue = value;
}
 


Название: Re: QObject утечка памяти
Отправлено: Kurles от Январь 12, 2013, 16:04
Что это вообще такое?  :o


Название: Re: QObject утечка памяти
Отправлено: Igors от Январь 12, 2013, 16:18
Пользуйтесь тегом для выделения кода. Также приведенный фрагмент недостаточен чтобы посоветовать что-то конкретное.
Интересует также вообще вопросы как Qt 4.7 работает с памятью и почему так неэкономно её расходует.
"Это Qt неэкономно расходует - я тут ни при чем!"  :)
Создавая контейнер объектов унаследованных от QObject надо считаться с тем что базовый класс достаточно "жирный", значит если элементов много, то и памяти сожрется прилично. Неплохо бы замерить размер элемента и сопоставить с их числом

Код:
	list->at(555)->setValue(value);
Возможно это просто "для примера", но никто не обещал что контейнер имеет > 555 элементов



Название: Re: QObject утечка памяти
Отправлено: Авварон от Январь 12, 2013, 16:53
Кстати вопрос знатокам - каков размер пустого QObject'а (а точнее, QObjectPrivate)?


Название: Re: QObject утечка памяти
Отправлено: GreatSnake от Январь 12, 2013, 17:03
2 Маус:
Коли не будут задействованы signal/slot, смысла в наследовании от QObject нет никакого.


Название: Re: QObject утечка памяти
Отправлено: m_ax от Январь 12, 2013, 17:15

CMyBase myObject;
вызываем myObject->setMyItem(value);

в объекте идет цепочка вызовов уже распределенных (по памяти) объектов
и за 500-700 вызовов подряд наблюдаем большую утечку памяти (рост с 600 мб до 2 гб занятой прогой памяти) и после этого программа выбрасывает. Интересует также вообще вопросы как Qt 4.7 работает с памятью и почему так неэкономно её расходует.

Код
C++ (Qt)
class CMyBase : public QObject
{
Q_OBJECT
public:
CMyItem* MyItem;
bool setMyItem(QVariant value);
}
bool CMyBase::setMyItem(QVariant value)
{
return MyItem->setValue(value);
}
 
 
class CMyItem : public QObject
{
Q_OBJECT
public:
       QList<CMySubItem>* list;
       bool setValue(QVariant value);
}
bool CMyItem:: setValue(QVariant value)
{
list->at(555)->setValue(value);
return true;
}
 
class CMySubItem : public QObject
{
Q_OBJECT
public:
       QVariant myValue;
       bool setValue(QVariant value);
}
bool CMySubItem ::setValue(QVariant value)
{
myValue = value;
}
 

Странно, что это, вообще, работает..


Название: Re: QObject утечка памяти
Отправлено: Igors от Январь 12, 2013, 17:21
Кстати вопрос знатокам - каков размер пустого QObject'а (а точнее, QObjectPrivate)?
Код
C++ (Qt)
#include <QtGUI>
 
int main( void )
{
for (int i = 0; i < 100; ++i) {
QObject * test1 = new QObject;
QObject * test2 = new QObject;
printf("size = %ld (%p, %p)\n", (char *) test2 - (char *) test1, test1, test2);
}
return 0;
}
 


Название: Re: QObject утечка памяти
Отправлено: Авварон от Январь 12, 2013, 17:35
Код
C++ (Qt)
#include <QtGUI>
 
int main( void )
{
for (int i = 0; i < 100; ++i) {
QObject * test1 = new QObject;
QObject * test2 = new QObject;
printf("size = %ld (%p, %p)\n", (char *) test2 - (char *) test1, test1, test2);
}
return 0;
}
 

Интересный подход:) И даже верный, (sizeof(QObjectPrivate) + sizeof(QObject)) == 128 (112 приват, поинтер на него+поинтер на втейбл QObject'а).


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 12, 2013, 17:36
Код действительно работает, просто там >10 тыс. строк в модуле, поэтому пришлось "вырезать лишнее". Проблема возникает когда мы изменяем значение используя функцию класса
CMyBase::setMyItem(value)
если же мы напрямую меняем значение (используя цепочку указателей):
myObject->myItem->list->at(555)->value
тогда работает.
Но конечно это не решение проблемы.
Попробую убрать наследование от QObject...

Вообще удивительно, почему программа 7 мб разворачивается в памяти на 500 мб. Конечно создаются начальные данные (1 мб), загружаются библиотеки на 30 мб, но 500 мб это уж чересчур...

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


Название: Re: QObject утечка памяти
Отправлено: m_ax от Январь 12, 2013, 17:42
Код действительно работает, просто там >10 тыс. строк в модуле, поэтому пришлось "вырезать лишнее". Проблема возникает когда мы изменяем значение используя функцию класса
CMyBase::setMyItem(value)
если же мы напрямую меняем значение (используя цепочку указателей):
myObject->myItem->list->at(555)->value
тогда работает.
Но конечно это не решение проблемы.
Попробую убрать Q_OBJECT...

Вообще удивительно, почему программа 7 мб разворачивается в памяти на 500 мб. Конечно создаются начальные данные (пару сотен кб.), но 500 мб это уж чересчур...

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

Q_OBJECT здесь нипричём..
Ошибка у вас в совсем другом( 


Название: Re: QObject утечка памяти
Отправлено: Авварон от Январь 12, 2013, 17:43
Код действительно работает, просто там >10 тыс. строк в модуле, поэтому пришлось "вырезать лишнее". Проблема возникает когда мы изменяем значение используя функцию класса
CMyBase::setMyItem(value)
если же мы напрямую меняем значение (используя цепочку указателей):
myObject->myItem->list->at(555)->value
тогда работает.
Но конечно это не решение проблемы.
Попробую убрать наследование от QObject...

Вообще удивительно, почему программа 7 мб разворачивается в памяти на 500 мб. Конечно создаются начальные данные (пару сотен кб.), но 500 мб это уж чересчур...

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

Тебе же сказали, проблема в том, что ты наследуешь QObject. Умнож количество айтемов на 128 и посмотри, сколько получилось.


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 12, 2013, 17:46
"Тебе же сказали, проблема в том, что ты наследуешь QObject"
там около 50 тыс. значений, созданных в разное время. Все работает, пока циклом не пытаюсь изменить (не создать, а только изменить) несколько сотен значений сразу. Резко растет память, причем на каждое изменение значения растет на 200 кб.


Название: Re: QObject утечка памяти
Отправлено: m_ax от Январь 12, 2013, 17:56
Вероятнее всего, Маус просто тупо забыл выделить память под список или какой-нить айтем:
Код
C++ (Qt)
...
public:
CMyItem* MyItem;
...
 
Код
C++ (Qt)
...
public:
       QList<CMySubItem>* list;
...
 

А потом удивляется, почему при записи всё падает..


Название: Re: QObject утечка памяти
Отправлено: Old от Январь 12, 2013, 18:24
Интересует также вообще вопросы как Qt 4.7 работает с памятью и почему так неэкономно её расходует.
Наверное потому, что Qt пишут люди не так хорош разбирающиеся в программировании, как вы. :)

То что ты привел в качестве кода, никак не сможет помочь в поисках утекающей памяти. Если не считать некоторых неясностей с тем, кто и что присваивает значения всяким MyItem и list, и явным не соответствием этого
Код
C++ (Qt)
       QList<CMySubItem>* list;
и этого
Код
C++ (Qt)
list->at(555)->setValue(value);

все что делает этот код, это устанавливает QVariant новое значение.
Проверить утечку при присвоении QVariant легко, но я уверен, что там никаких утечек нет, поэтому лучше показать больше вашего кода. ;)


Название: Re: QObject утечка памяти
Отправлено: kambala от Январь 12, 2013, 18:38
Тебе же сказали, проблема в том, что ты наследуешь QObject
я тоже за этот вариант.

если надо хранить произвольные данные в классе, то можно попробовать вместо QVariant использовать void * и enum для типа, хотя не могу сказать насколько это оправдано по количеству изменений в существующей программе, приросту производительности и уменьшению потребления памяти.


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 12, 2013, 18:39
утечка идет не в момент присваивания значения, а при вызове метода, который это делает. Такое ощущение, что память каждый раз распределяется заново.


Название: Re: QObject утечка памяти
Отправлено: Bepec от Январь 12, 2013, 18:51
Мб у вас там идёт динамическое создание этого класса каждый раз?


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 12, 2013, 19:52
Нет, экземпляр класса
CMyItem* MyItem;
создается только 1 раз при инициализации CMyBase, затем идет только добавление/изменение элементов в списке list.

П.С. QObject убрал, проблема осталась. Объем занимаемой программой памяти увеличился с 756 мб до 1256 мб.;-)


Название: Re: QObject утечка памяти
Отправлено: Old от Январь 12, 2013, 19:59
Нет, экземпляр класса
CMyItem* MyItem;
создается только 1 раз при инициализации CMyBase, затем идет только добавление/изменение элементов в списке list.
Вот и показал бы, как инициализируется CMyBase и list.


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 12, 2013, 20:58
Смастерил 2 примера, один с QObject, другой - без, по созданию/изменению 1 млн. объектов, память занимают 223 мб и 74 мб соответственно, но проблему (на примере) пока не увидел. Буду копать дальше


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 13, 2013, 00:07
Нашел ответ... Проблема крылась в другом объекте, который вызывался и потреблял память. В общем никакой утечки памяти нет.
Всем откликнувшимся спасибо, без участия сообщества я бы так быстро не разобрался;-).
(Тему можно удалить;-)


Название: Re: QObject утечка памяти
Отправлено: kambala от Январь 13, 2013, 00:18
но наследование от QObject лучше все-таки убери


Название: Re: QObject утечка памяти
Отправлено: Маус от Январь 13, 2013, 10:44
QObject конечно убрал :)


Название: Re: QObject утечка памяти
Отправлено: xokc от Январь 14, 2013, 10:42
(Тему можно удалить;-)
Я бы не удалял, а наоборот, всячески "пропагандировал" как пример правильного перехода от поиска пылинки в чужом глазе к нахождению бревна в своём. Ну и как пример грамотного понимания топикстратера выдаваемых ему советов.