LINUX.ORG.RU

Помогите! Происходит утечка памяти!


0

0

Недавно обнаружил пренеприятнейшее явление: программы, которые написаны при помощи Kdevelop 2.1 и откомиплированы в нём же, используя компилятор GCC версии 2.96, делают одну очень нехорошую вещь: при удалении объекта вызывается деструктор, объект удаляется,казалось бы, всё, как положено, но память при этом не высвобождается (!!!?).Это легко тслеживается с помощью команды ps -A --format=%c --format=%mem |grep имя программы. При работе с большим количеством объектов, их динамическом добавлении и удалении, в частности, работе с компонентами типа QCanvasSprite, память пожирается приложением, оно начинает пухнуть, хотя этого быть не должно. Примечательно, что этим страдают не только программы, написанные мной, но и все программные примеры из документации по разработке с использованием библиотек QT. Не знаю, в чём тут дело - может быть, в компиляторе ?. Система у меня -RedHat 7.3.Помогите, пожалуйста, вопрос для меня далеко не праздный.

anonymous

Все в порядке. Так работает malloc.

asd
()

malloc я не использовал, память я выделял под экземпляры QT-ных классов с помощью new, а удалял с помощью delete pointer. У меня сложилось мнение, что данное непотребство происходит именно при работе с QT-библиотеками, хотя странно, мистика какая-то, но факт есть факт. Даже станданртные шаблоны программ в KDevelop, где есть вызов какого-нибудь виджета, скажем, диалог QFileDialog, вызываемый при помощи функции QString fileName = QFileDialog::getOpenFileName(0,0,this); засоряют таким образом память.Для эксперимента я попробовал следующую простую вещь: for (int i=0;i<=100;i++) { QFileDialog* dlg=new QFileDialog(); delete dlg; } Результаты: До выполнения цикла память приложения - 2.4 М после - 4.1 М

anonymous
()

купи еще памяти, она сейчас дешевая...

SadStork
()

К сожалению, это не выход для меня. Прога должна работать круглыми сутками на произодстве, поэтому рано или поздно она заберет достаточно памяти, чтобы это сказалось на ее работоспособности и работоспособности очень важных прог, выполняющих специфические задачи.

anonymous
()

new использует malloc. А free (delete) не отдает память операционке, а оставляет ее в пуле процесса. Стандартное поведение описано в любой книге по программингу.

asd
()

Из тех книг, что у меня под рукой, я ничего, кроме: delete pointer; pointеr=NULL; не нашел. Есть ли какое-нибудь стандартное решение? Дело в том, что если я нашел бы это в своей литературе, я не полез бы на форум. Я был бы очень благодарен, если бы мне кто-нибудь помог

anonymous
()

>new использует malloc. А free (delete) не отдает память операционке, а оставляет ее в пуле процесса. Стандартное поведение описано в любой книге по программингу. Киньте plz ссылочку на такую книжку, желательно online.

LegaT
()

Еще одна деталь: я повторил эксперимент, но уже с простым указателем на integer : for (int i=0;i<=10000;i++) { int * p=new int[500]; delete p; p=NULL; } В этом случае все прекрасно очищается и память отдается операционке также, как и берется.То же самое, если даже не писать p=NULL.

anonymous
()

Какие результаты будут если в этом цикле заменить 100 на 200?

for (int i=0;i<=100;i++) { 
  QFileDialog* dlg=new QFileDialog(); 
  delete dlg; 
}

asd
()

Может дело не в бабине, а баг в Qt? Можно переопределить new delete и посмотреть, когда происходит new без delete.

Потом еще вопрос, как ты смотришь кол-во свободной памяти? Какая ОС?

anonymous
()

в догонку: это вообще может быть не баг а фича. Я не знаю как в линуксе,
хотя есть подозрение, что это общее для всех систем... Может
происходить вот что: если вызвать malloc(очень моного) заюзать эту
память, потом free, ps...|grep скажет, что используется много памяти,
хотя на самом деле это не так. Все дело в страничной организации
виртуальной памяти. Используется ленивый алгоритм освобождения.
Страницы просто помечаются как свободные, а отображение реальной памяти
на память процесса остается. Проверить сие просто: надо завести 2
экзепляра проги типа

...main(...)
{
   char *p = (char*) malloc(1024*1024*256); //или сколько там есть
   for( i=0; i<1024*1024*256; i++ ) p[i] = 0;
   free(p);
   for(;;){}
}

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

Удачи.

anonymous
()

это называется copy-on-write стратегия и никакого оношения к рассматриваемому вопросу не имеет

anonymous
()

copy-on-write действительно никакого оношения к рассматриваемому вопросу не имеет, только то что я описал не copy-on-write

anonymous
()

робяты кто-ж делает delete после new[] ? после new нужно делать delete, а после new[] нужно делать delete[] а после malloc ясен пень free кто нарушит сеи простые правила получит undefined behavior - то-бишь отформатится винт - виноваты только вы :)

Fidoman

anonymous
()

Утечку можно посмотреть спец. средствами, типа dmalloc, на правдивость ps вряд ли тут надо надеяться - так может работать менеджер памяти системы, т.е. по delete действительно память может помечаться как освобожденная, но оставаться принадлежащей данному процессу. И конечно же для new[] вызывать delete[].

PETER ★★
()

Уже 3 раз за последний год поднимается эта тема.

!!! ЭТО ФИЧА Qt !!!

В нижеприведенном цикле:

for (int i=0;i<=100;i++) {
QFileDialog* dlg=new QFileDialog();
delete dlg;
}
память будет "течь", факт. Происходит это потому, что при создании
QWidget'а порождаются разные обработчики, которые пихаются в очередь
и уничтожаются только тогда, когда управление попадает в main event
loop. То есть, "отеденная" память очистится, когда управление вернется
в главный цикл.


Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Я очень близок к такому же мнению. Только память не восстанавливается и при выходе из цикла : for (int i=0;i<=100;i++) { QFileDialog* dlg=new QFileDialog(); delete dlg; } Да и не в цикле этом дело. Я его просто для быстрой проверки запускал. Такие же результаты можно получить, если в QT-проге, сделанной визардом KDevelop-ским, просто сидеть и нажимать на кнопку Open , а потом 'Cancel' .Не знаю, возвращается ли управление в main event loop в этом, простейшем случае, но память съедается. Еще один очень красноречивый пример -'canvas' из QT-ных экзамплов. Накидывая кучу графических объектов на канву, а потом вызывая пункт меню 'Erase canvas' , получаем такой же, классический, как я уже думаю, для QT, зажор памяти.

anonymous
()
Ответ на: комментарий от anonymous

Ну, короче, мне сейчас влом возиться с Qt 3. Я все еще под 1.4x сижу.

Так вот, там (Qt 1.44) все в порядке, специально много раз проверял. Память часто начинает течь, если по какой-то причине нет возврата в главный цикл. Как только возвращаемся в главный цикл - память освобождается. Обрати внимание, что она при этом НЕ отдается системе. Т.е., симптомы таковы: создаем/освобождаем виджеты - прога пухнет. Выскакиваем в главный цикл - прога перестает пухнуть, но НЕ худеет.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Плохо, что не худеет, потому что в следующий раз при необходимости прога будет брать память не из своих свободных(освобожденных) резервов, а опять же у операциоки. Сие установлено при помощи команды free. А иначе какие проблемы? Можно было бы и в ус не дуть - прога сама распоряжается взятой у системы памятью - освобождает и снова использует.Но ведь это не так.Очевидно, что не отданная системе память не используется программой вновь, когда возникает потребность.

anonymous
()
Ответ на: комментарий от anonymous

anonymous (*) (2003-03-13 07:28:42.352):
> Плохо, что не худеет, потому что в следующий раз при необходимости прога
> будет брать память не из своих свободных(освобожденных) резервов, а опять
> же у операциоки.
ДА НЕТ ЖЕ!!!!

Уходи периодически в главный цикл, не теряй память сам (в смысле, не забывай
delete где надо) и прога пухнуть не будет!!!

Еще раз:

Пока ты создаешь/удаляешь видгеты минуя главный цикл, прога потихоньку пухнет.
Потом ты отдаешься в главный цикл - память возвращается в свободный пул, но
не отдается операционке.

Потом ты опять начинаешь создавать/удалять видгеты - и она НЕ пухнет, пока
ты не переплюнул предыдущий маразм.


> Очевидно, что не отданная системе память не используется
> программой вновь, когда возникает потребность.

Я специально долго гонял в свое время Qt 1.43 и Qt 1.44 на этот предмет.
Утверждаю, что там все в порядке. Но часто КАЖЕТСЯ, что память течет. Почему
- см. выше.

Хотя, старшие Qt я сам не гонял. Но слышал от людей, что там тоже все
в порядке, по крайней мере в Qt 2.x.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Спасибо, Die-Hard, я тебя понял очень хорошо, и не сомневаюсь, что всё это так. Да и проблема для меня сейчас потеряла остроту всвязи с найденным оптимальным алгоритмом(отнюдь не устранением элементарных ошибок вроде поери delete, где надо).Но не мог бы ты научить меня, тёмного человека(без шуток) в сфере программирования под Linux, как определить доподлинно, возвращается ли программа в главный цикл?

anonymous
()
Ответ на: комментарий от anonymous

> как определить доподлинно, возвращается ли программа в главный цикл?

Типа, если специально не извращаться, то она (программа) почти все время в нем и торчит...

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.