Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Делфи 5. Утечка памяти.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
GetSmart
Есть проект на Делфи 5. Работает сутки и более. В процессе работы вижу в диспетчере задач, что память процесса растёт на 100-200-300 МБ. За сутки может 300 отъесть. Но в алгоритме там реально памяти требуется всего 20-40 МБ. Однако там сотни тысяч-миллионы раз происходит работа со строками (от 1 до 100000 символов длиной). Это единственное подозрение на утечку.

Я правильно понимаю, что если я в процедуре создал строку, то на выходе из этой процедуры Делфа должна сама освобождать указатель строки? И аналогично, если я заполненной строке присваиваю новое значение, то делфа должна сама старую строку удалить из динамической памяти? Или это должен делать программист сам?
AHTOXA
А работа с памятью через New/Dispose или GetMem/FreeMem используется? Плагины? Интерфейсы? COM/OLE?
Если нет, то скорее всего всё нормально. Просто происходит фрагментация кучи, и при очередном распределении большой строки для неё не находится свободного непрерывного места, и приходится выделять новый кусок. После достижения какого-то размера этот процесс устаканится, и рост памяти прекратится.
GetSmart
Цитата(AHTOXA @ Jan 23 2012, 21:19) *
А работа с памятью через New/Dispose или GetMem/FreeMem используется?

Это есть при запуске. Как раз выделяются 20-40 МБ. Далее, буквально раз в 5 минут выделяется по 10-100 байт через GetMem(). За сутки GetMem() может выделить от силы мегабайт, скорее в 10 раз меньше.

Цитата
Плагины? Интерфейсы? COM/OLE?

Только класс TNMHTTP.

Цитата
Если нет, то скорее всего всё нормально. Просто происходит фрагментация кучи, и при очередном распределении большой строки для неё не находится свободного непрерывного места, и приходится выделять новый кусок.

На 99% не верю. Но хотелось бы как-то проверить это дело. Что показательно, так это то, что выделяемые каждый раз строки полностью удаляются (должны). Фактически строк, которые живут долго и создают фрагментацию я не имею. Хотя... Есть такая штука Memo, в которую медленно добавляется текст и через сутки его объём доходит до 30-200 КБ. Могу добавлять этот текст не в Memo, а в файл, для проверки версии.
Могу даже полностью убрать вызовы GetMem() в процессе работы, выделив мегабайт заранее и потом внутри него линейно выделять куски.
Но хотелось бы не делать лишней работы, и узнать заранее что надо, а что не надо.

Цитата(AHTOXA @ Jan 23 2012, 21:19) *
После достижения какого-то размера этот процесс устаканится, и рост памяти прекратится.

Не заметил. Стабильно растёт. Тем более, если уже теряется в 10 раз больше, чем необходимо, то это реальный беспредел.
AHTOXA
Цитата(GetSmart @ Jan 23 2012, 22:27) *
Только класс TNMHTTP.

Ни о чём не говоритsm.gif Но это вроде как что-то из поставки дельфи? Тогда явные ляпы маловероятны.
Цитата
На 99% не верю. Но хотелось бы как-то проверить это дело. Что показательно, так это то, что выделяемые каждый раз строки полностью удаляются (должны).

Не верите во что? Строки в дельфи - очень надёжная штука. Мой опыт это подтверждает. У меня есть приложения, которые работают месяцами, при очень активном использовании строк. Так что думаю, что дело не в них.
Цитата
Не заметил. Стабильно растёт. Тем более, если уже теряется в 10 раз больше, чем необходимо, то это реальный беспредел.

Если есть возможность, то распределяйте/освобождайте память через свою спецфункцию, со счётчиком. То же и со строками. Метод простой и очень эффективный.
_Pasha
memavail() и maxavail() выведите в отдельный тред и вызывайте / логьте через какой-то промежуток времени. Если фрагментация - станет ясно через часок.
GetSmart
Цитата(AHTOXA @ Jan 23 2012, 22:03) *
Не верите во что? Строки в дельфи - очень надёжная штука.

Там было о фрагментации написано, а не о строках.

Цитата(AHTOXA @ Jan 23 2012, 22:03) *
Если есть возможность, то распределяйте/освобождайте память через свою спецфункцию, со счётчиком. То же и со строками. Метод простой и очень эффективный.

Со строками тот ещё гемор. Тыщи строк кода переписывать и делать через жпу, если я правильно понял. Потому как выражения типа Memo2.Lines.Add(s1+s2) придётся в 10 строк переписывать.

Свой GetMem() писать тоже занятие тяжкое и долгое. Если конечно делать качественно, без потерь памяти.

Цитата(_Pasha)
memavail() и maxavail() выведите в отдельный тред и вызывайте / логьте через какой-то промежуток времени. Если фрагментация - станет ясно через часок.

Не пойму, чем эта статистика лучше чем из диспетчера задач?
ARV
основные утечки памяти происходят в VCL - примитивная работа со строками ее не дает. в соседней теме я вас советовал, и здесь посоветую: обновите Delphi до 7-й версии (с сервиспаком). VCL в ней заметно лучше (меньше утечек).
GetSmart
Поставил D7.3.3. Возникла другая грабля. Там нет компонента TNMHTTP. А какой наиболее подходящий для работы с HTTP протоколом (из наименее навороченных) надо выяснять.

Upd.
Возможно IdHttp.
_Pasha
Цитата(GetSmart @ Jan 23 2012, 21:14) *
Не пойму, чем эта статистика лучше чем из диспетчера задач?

Хоть уже и не актуально, но :
мы тогда говорили о фрагментации кучи, я предлагал таким образом установить именно факт утечки памяти из-за фрагментации.
RabidRabbit
Везде, где есть New, GetMem или Create - увеличивать глобальный счётчик и писать в лог, где Dispose, FreeMem или Free - счётчик уменьшать и тоже писать в лог. Хорошо помогает (мне, во всяком случае), а на строки в Дельфе можно не пенять (как уже заметили).
_Pasha
Та ну... Если уж перехватывать манагер памяти, то не лучше ли сразу переходить от указателей к дескрипторам и предусматривать дефрагментацию кучи? Понятное дело, разыменование дескриптора в 1,5- 2 раза медленнее, зато для интенсивных преобразований разных деревьев может очень даже пригодиться.
GetSmart
Почти нашёл косяк.
Переделывать под Делфи 7 я так и не решился, т.к. надо изучать новый компонент и отлаживаться на нём.


Сделал как ранее предлагал, вместо записи в Memo пишу в файл, вместо вызова GetMem(), заранее выделяю мегабайтный буфер и потом внутри него выдаю частями. Сделал обёртку GetMem() и FreeMem() для сбора статистики. В итоге обнаружилась своя утечка на ~50 МБ/сутки. Но не 300. Это было в поиске уникальных строк, шастая по быстрому дереву поиска, когда даже если строка полностью идентична, то создавались ненужные ветви дерева. Тогда как запланировано, что ветви дерева должны создаваться только для разделения уникальных строк. Короче, идя по дереву с новой строкой я зря создавал ветви "на лету", тогда как надо было сперва дойти до конца строки и только если она отлична, создавать. А 50 МБ превращалось в 300 уже наверно из-за фрагментации и постоянно увеличивающегося текста в Memo. По крайней мере, пока с моей утечкой 50 МБ и мегабайтными буферами не вижу доп.утечек.

Upd.
Даже не 50, а примерно 20. И не утечка, а незапланированная и бесполезная трата памяти. В итоге что-то её увеличило в 10 с лишним раз.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.