Моя программа никогда не освобождает память обратно. Зачем?
У меня есть программа MDI. При запуске требуется 2-3 МБ оперативной памяти. Затем в этой программе я создаю около 260 дочерних окон MDI (каждое имеет TStringGrid, растровое изображение и некоторые другие элементы управления) и отображаю некоторые данные. Приложению требуется около 500 МБ для загрузки всех этих окон. Если я закрою каждый дочерний MDI вручную, приложение все равно использует 160 МБ ОЗУ. Почему не возвращается несколько МБ ОЗУ? Должен ли я беспокоиться об этом? 160 МБ это много для системы, которая имеет только 1 ГБ или RAM!
Примечание: я использую столбец РАБОЧИЙ НАБОР в диспетчере задач, чтобы увидеть статистику ОЗУ. Может быть, мне нужен лучший инструмент для чтения использования оперативной памяти. (Частный рабочий набор чуть меньше рабочего набора).
Это не утечка!
FastMM (установлен на агрессивную) указывает на отсутствие утечки памяти при закрытии программы. См. Мой пост Ответ для дополнительных доказательств того, что это не утечка.
Я выпускаю вещи
Многие люди говорили мне, что закрытие дочернего окна только скрывает это. Я знаю это. Я использую "Action:= caFree", чтобы фактически выпустить формы. Каждая форма отвечает за освобождение элементов управления, которые она содержит.
Ответ
Я обнаружил, что за это отвечает FastMM. Смотрите ответ, который я разместил ниже.
Delphi 7, Win 7 32 бит
Похожие посты:
Можно ли очистить память?
Когда вызывать SetProcessWorkingSetSize? (Убедить менеджера памяти освободить память)
5 ответов
Ответ:
Я просто удалил FastMM из своего проекта, и программа освободила несколько МБ после освобождения всех этих дочерних окон. Многие могут возразить, что это не является неправильным поведением и что FastMM делает это для того, чтобы сделать некоторую странную оптимизацию памяти. Они могут быть правдой. Однако, это может быть хорошо для МОЕГО приложения, но не может быть хорошим для других работающих приложений.
Итак, по крайней мере, мы знаем, кто это вызывает. Я целый день волновался, что программа может вытекать из памяти как старое ведро. Теперь я с облегчением.
ОБНОВИТЬ:
Чтобы подтвердить, что это поведение сгенерировано FastMM (как предложено Барри Келли), я создал вторую программу, которая выделяла МНОГО ОЗУ. Как только в Windows кончилось ОЗУ, использование памяти моей программой вернулось к своему первоначальному значению.
(Примечание: я не говорю, что в FastMM есть ошибка!)
Моя программа не подтекает. Задача решена.
Диспетчер задач не подходит для обнаружения утечек памяти. Delphi выделяет большие блоки памяти и сохраняет их для дальнейшего использования, поэтому ожидается некоторое увеличение выделенной памяти даже после освобождения всех ресурсов. Любые другие результаты (и более подробные ответы) можно получить только с помощью специализированных инструментов анализа памяти. AQTime - это первое, что приходит на ум, или, если вы найдете старый, но полезный MemProof, он вам очень поможет (MemProof бесплатен, а для анализа памяти удобнее, чем AQTime).
Вполне возможно, что FastMM не показывает утечки памяти после завершения работы приложения (например, потому что все объекты являются принадлежащими TComponents, а владелец освобождает их).
Но в то же время, пока эти компоненты работают, они все еще могут быть и не достаточно быстро освобождены.
Вы использовали модуль FastMM, который показывает форму с текущим использованием памяти?
<Изменить>
Это FastMMUsageTracker.pas
в каталоге ...\FastMM\Demos\Usage Tracker
,
Используйте это устройство, затем позвоните ShowFastMMUsageTracker
функция в нем. Вы можете обновлять эту форму время от времени, чтобы увидеть, как растет потребление памяти. Я положил FastMMUsageTrackerProject
Пример он-лайн, включая обновление FastMM4, упрощающее проверку и устранение утечек памяти:
- форма в
FastMMUsageTracker
Теперь модуль можно изменять, и элементы управления в нем привязываются правильным образом. - есть новый
FastMmBootstrapUnit
блок, облегчающий отладку определенных утечек памяти
На прошлой неделе у меня была под рукой сторонняя DLL, которая не была написана на Delphi.
В DLL произошла утечка памяти при использовании вызовов Windows GlobalAlloc, которые не отслеживаются FastMM.
NB: я собираюсь опубликовать обновление для FastMM на
--jeroen
Если вы закрываете форму MDI, она не освобождается автоматически. Используйте Action = caFree (Google для этого), чтобы убедиться, что форма также освобождена.
Основное ограничение отслеживания утечек памяти в FastMM заключается в том, что он может работать только при закрытии программы. Возможно, вы по-прежнему храните ссылки на объекты или другие данные, которые очищаются при завершении работы программы, но остаются до тех пор.
Например, когда вы закрываете дочерние окна MDI, вы вызываете Free или Release для них или просто заставляете их исчезать? Если они спрятаны, но не освобождены, они все равно останутся в памяти.