Russian Qt Forum
Ноябрь 24, 2024, 23:23 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QObject утечка памяти  (Прочитано 13195 раз)
Маус
Гость
« : Январь 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;
}
 
« Последнее редактирование: Январь 14, 2013, 12:09 от Пантер » Записан
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« Ответ #1 : Январь 12, 2013, 16:04 »

Что это вообще такое?  Шокированный
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Январь 12, 2013, 16:18 »

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

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

Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #3 : Январь 12, 2013, 16:53 »

Кстати вопрос знатокам - каков размер пустого QObject'а (а точнее, QObjectPrivate)?
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Январь 12, 2013, 17:03 »

2 Маус:
Коли не будут задействованы signal/slot, смысла в наследовании от QObject нет никакого.
Записан

Qt 5.11/4.8.7 (X11/Win)
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #5 : Январь 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;
}
 

Странно, что это, вообще, работает..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Январь 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;
}
 
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Январь 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'а).
Записан
Маус
Гость
« Ответ #8 : Январь 12, 2013, 17:36 »

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

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

Если никто не сталкивался, попробую завтра выложить рабочий пример. В крайнем случае обратимся в техподдержку, благо у нас куплена лицензия.
« Последнее редактирование: Январь 12, 2013, 17:43 от Маус » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #9 : Январь 12, 2013, 17:42 »

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

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

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

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

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #10 : Январь 12, 2013, 17:43 »

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

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

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

Тебе же сказали, проблема в том, что ты наследуешь QObject. Умнож количество айтемов на 128 и посмотри, сколько получилось.
Записан
Маус
Гость
« Ответ #11 : Январь 12, 2013, 17:46 »

"Тебе же сказали, проблема в том, что ты наследуешь QObject"
там около 50 тыс. значений, созданных в разное время. Все работает, пока циклом не пытаюсь изменить (не создать, а только изменить) несколько сотен значений сразу. Резко растет память, причем на каждое изменение значения растет на 200 кб.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #12 : Январь 12, 2013, 17:56 »

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

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

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #13 : Январь 12, 2013, 18:24 »

Интересует также вообще вопросы как Qt 4.7 работает с памятью и почему так неэкономно её расходует.
Наверное потому, что Qt пишут люди не так хорош разбирающиеся в программировании, как вы. Улыбающийся

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

все что делает этот код, это устанавливает QVariant новое значение.
Проверить утечку при присвоении QVariant легко, но я уверен, что там никаких утечек нет, поэтому лучше показать больше вашего кода. Подмигивающий
« Последнее редактирование: Январь 12, 2013, 18:25 от Old » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #14 : Январь 12, 2013, 18:38 »

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

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

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.202 секунд. Запросов: 23.