| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Утечка ВИРТУАЛЬНОЙ памяти? |
| Автор: zedx 18.5.2009, 20:35 | ||||
Собственно, ситуация: в проекте очень активно используются переменные TMemoryStream, причём само приложение многопоточное. (приложение - прокси-сервер, многопоточность - за счёт Indy (TIdHTTPServer)). Переменные создаются и уничтожаются как обычно:
За потоками Indy следит сам. Утечки и все исключения мониторю в EurekaLog, собственно, утечек памяти она не фиксирует. В процессе активного использования программы неумолимо растут затраты как оперативки, так и виртуальной памяти (мониторю в диспетчере винды). Оперативы у меня 1,5Гб, файл подкачки отключён полностью. Оперативку периодически, по таймеру, высвобождаю процедурой:
поставил таймер на 15 минут, к этому времени приложение успевает отхватить 250-300Мб озушки и почти столько же виртуальной памяти (при старте приложения используется всего - 10-15Мб). После вызова указанной процедуры оперативка высвобождается вся - приложение начинает занимать всего 1,5-3Мб, а вот виртуальная память растёт и дальше. И через определённое время, когда у винды виртуальная память кончается, моё приложение благополучно уничтожается (то-ли само вылетает, то-ли винда помогает)... Так вот, как подчищать виртуальную память, на подобии оперативки? И почему, вообще, память растёт, а не освобождается автоматом, коль уж утечек нет? |
| Автор: zedx 18.5.2009, 21:37 |
| Нет, блоков finalization в проге вообще нет, и по завершении тоже ничего не освобождаю. К тому же, если бы была ситуация как ты говиришь, то оперативка так глобально не освобождалась бы? Вот http://narod.ru/disk/8724130000/GeoCacher_20090515.rar.html эта прога с исходниками, может кто глянет опытным глазом? |
| Автор: kami 18.5.2009, 21:48 |
Да при чем тут finalization? Это было приведено в качестве явного примера возрастания потребления памяти вплоть до вылета, без явных утечек. освобождение может проходить где угодно - OnClose, Destroy и т.п. при завершении приложения. Ну, не могу сказать, что глаз у меня опытный, но посмотрим. |
| Автор: zedx 18.5.2009, 22:05 | ||||
Да я понял, но нету такого. При завершении приложения освобождаю мелочь - критические секции, и собственно, Indy - т.е. то, что создавалось при старте проги. А всё, что в процессе создаётся, в процессе же и уничтожаю... единственно, вот сюда приходит последняя переменная Resp.Body (TMemoryStream) которую я не уничтожаю - её по-идее должен инди освободить... все остальные стримы для этого потока, к этому моменту уже уничтожаются.
|
| Автор: zedx 18.5.2009, 23:12 |
| Самое интересное, что диспетчер задач винды, не обращает внимание на то, что происходит очистка озушки и в Хронологии использования файла подкачки (хотя повторюсь - файл подкачки отключён) - такая ровная восходящая линия, до момента выбрасывания/зависания проги... причём сама винда и проги не тормозят ничуть, т.е. опреративка-то свободна. А вот запуск фотошопа, в момент когда прога выжрала всю виртуалку, обломился, с ошибкой фотошопа - Файл подкачки слишком мал, для завершения операции. Странно это. |
| Автор: CodeMonkey 18.5.2009, 23:27 |
| Да ничего странного у вас нет. У вас либо нет утечки, но ошибка в логике (kami пример указал), либо утечка не памяти, а, скажем, объектов ядра (пример: создавать и не освобождать HBITMAP). Если первое - попробуйте захавать как можно больше памяти, потом сделать дамп выделения (в этом вам поможет FastMM). Ткните наугад в карту памяти - с хорошей вероятностью получите виновника неявной утечки. Если второе - то кроме mem-leak используйте другие утилиты - профайлеры ресурсов. А EL какая версия? Я помню там баг когда-то был с детектом mem-leak-ов. Попробуйте ещё под FastMM или обновите EL до 6.0.20. Добавлено @ 23:34 Да, кстати, после того, как разберётесь с проблемой, выкиньте вот это: SetProcessWorkingSetSize(MainHandle, DWORD(-1), DWORD(-1)); |
| Автор: zedx 18.5.2009, 23:46 | ||
Экврика как раз 6.0.20.
...новое для меня понятие, пошёл напрягать гугл |
| Автор: kami 19.5.2009, 00:06 |
| При наличии 15 вызовов VirtualAlloc потребление памяти от вызовов этой ф-и достигло высот в 18353952 байт. На 18-м программа скончалась. MemProof упрямо говорит, что проблема в выделении памяти. А именно: function PutFileToCache => X:=TSaveX.Create(true); // показывает пальцем сюда. И гораздо больше - просто вызов из function PutFlatFile => PutFileToCache. // и сюда Который, кстати, идет в двух местах этой процедуры. |
| Автор: zedx 19.5.2009, 00:13 | ||||||
т.е. поток не уничтожается? вот этот класс
и его процедура:
|
| Автор: kami 19.5.2009, 00:26 |
1. Пройдитесь отладчиком - я не могу скомпилировать код, т.к. не пользуюсь инди. А ковырять чужой код... ладно бы минимальный тестовый пример, в котором проявляется ошибка, а полный код 2. Скачайте себе профайлер и посмотрите сами что да как. |
| Автор: CodeMonkey 19.5.2009, 08:46 |
Посмотрите http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=943, http://www.automatedqa.com/products/aqtime/memproofusers/, http://www.automatedqa.com/products/aqtime/. |
| Автор: zedx 20.5.2009, 17:36 | ||
Поставил AQTime v6.20, интегрировался он в проект. Выбираю подозрительный модуль (с точки зрения утечки), правый клик мышью -> Profile xxx.pas В настройках выбрал профиль Allocation Profile. Запускаю, гоняю, вижу утечку в Диспетчере задач, закрываю прогу. AQT выдаёт мне репорт:
Очень много строчек VCL native memory - но размер мизерный, а вот 2 последние строчки: Reserved Virtual Memory - по 5 Мб - я так понимаю, это и есть утечка, т.к. строчек Committed после не наблюдается? Не понимаю, как перейти теперь по этой инфе (Address 0x08010000) в исходники, на конкретную строку/процедуру, где эта утечка происходит... Что делать? |
| Автор: zedx 20.5.2009, 23:11 | ||
| Похоже, что нашел основную утечку (правда, методом тыка - по-этапно исключая из кода то, что можно отключить. Как находить утечки с AQTime так и не выяснил). Виновником оказался визуальный компонент от TMS: AdvStringGrid. Я использую его для динамического добавления строк+раскраска (причём всё это происходит из потока). Помогло исключение из кода строчек:
... и как мне теперь, интересно, строки писать? |
| Автор: kami 24.5.2009, 19:34 |
Нехорошо обращаться к визуальным компонентам из потока. Сделать это хотя бы из метода синхронизации потока. Поэтому и могут идти утечки. А исходный код компонентов доступен? Добавлено через 1 минуту и 25 секунд Тоже не помогу. Для этой цели использую исключительно FastMM, а AQ - для замера производительности сложных участков кода. |
| Автор: zedx 27.5.2009, 12:14 | ||||
Вся работа с компонентом идёт из критической секции:
|
| Автор: kami 27.5.2009, 12:24 |
а код все равно выполняется в доп.потоке. Добавлено через 1 минуту и 56 секунд а должен - в основном |