Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Утечка ВИРТУАЛЬНОЙ памяти? а с оперативкой всё ОК 
:(
    Опции темы
zedx
Дата 18.5.2009, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Собственно, ситуация: в проекте очень активно используются переменные TMemoryStream, причём само приложение многопоточное. (приложение - прокси-сервер, многопоточность - за счёт Indy (TIdHTTPServer)). Переменные создаются и уничтожаются как обычно:
Код

     mem:= TMemoryStream.Create;
  try

  finally
    mem.free;
  end;

За потоками Indy следит сам.
Утечки и все исключения мониторю в EurekaLog, собственно, утечек памяти она не фиксирует.
В процессе активного использования программы неумолимо растут затраты как оперативки, так и виртуальной памяти (мониторю в диспетчере винды). Оперативы у меня 1,5Гб, файл подкачки отключён полностью.
Оперативку периодически, по таймеру, высвобождаю процедурой:
Код

procedure FreeMemory;
var
MainHandle: THandle;
begin
    if Win32Platform = VER_PLATFORM_WIN32_NT then
    begin
    MainHandle := OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessID);
    SetProcessWorkingSetSize(MainHandle, DWORD(-1), DWORD(-1));
    CloseHandle(MainHandle);
    end;
end;

поставил таймер на 15 минут, к этому времени приложение успевает отхватить 250-300Мб озушки и почти столько же виртуальной памяти (при старте приложения используется всего - 10-15Мб). После вызова указанной процедуры оперативка высвобождается вся - приложение начинает занимать всего 1,5-3Мб, а вот виртуальная память растёт и дальше. И через определённое время, когда у винды виртуальная память кончается, моё приложение благополучно уничтожается (то-ли само вылетает, то-ли винда помогает)...
Так вот, как подчищать виртуальную память, на подобии оперативки?  И почему, вообще, память растёт, а не освобождается автоматом, коль уж утечек нет?
PM MAIL   Вверх
kami
Дата 18.5.2009, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(zedx @  18.5.2009,  20:35 Найти цитируемый пост)
 И почему, вообще, память растёт, а не освобождается автоматом, коль уж утечек нет?

Вполне возможно, что утечки не фиксируются благодаря тому, что используемая память высвобождается при завершении приложения. А при работе - просто добавляются новые данные.

Пример:
Код

var
  list:TList;

procedure TMyClass.FillList;
for i:=0 to x do
  begin
    MyMemStream:=TMemoryStream.Create;
    // заполняем данными, работаем
    list.Add(myMemStream); // вносим в список для (к примеру) передачи другому потоку
  end; // и забываем.


Если процедура с этим циклом будет выполняться многократно - будет жесть.
А утечек не будет, потому что в finalization будет код:
Код

finalization
  for i:=0 to List.Count-1 do
    TObject(List[i]).Free;
  List.Free;
end.


Просмотрите свой код - наверняка что-то подобное есть.
PM MAIL WWW   Вверх
zedx
Дата 18.5.2009, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Нет, блоков finalization в проге вообще нет, и по завершении тоже ничего не освобождаю. 
К тому же, если бы была ситуация как ты говиришь, то оперативка так глобально не освобождалась бы? 
Вот тут эта прога с исходниками, может кто глянет опытным глазом? 
PM MAIL   Вверх
kami
Дата 18.5.2009, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(zedx @  18.5.2009,  21:37 Найти цитируемый пост)
Нет, блоков finalization в проге вообще нет, 

Да при чем тут finalization?
Это было приведено в качестве явного примера возрастания потребления памяти вплоть до вылета, без явных утечек.
освобождение может проходить где угодно - OnClose, Destroy и т.п. при завершении приложения.
Цитата(zedx @  18.5.2009,  21:37 Найти цитируемый пост)
может кто глянет опытным глазом

Ну, не могу сказать, что глаз у меня опытный, но посмотрим.
PM MAIL WWW   Вверх
zedx
Дата 18.5.2009, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Цитата(kami @  18.5.2009,  21:48 Найти цитируемый пост)
освобождение может проходить где угодно - OnClose, Destroy и т.п. при завершении приложения.

Да я понял, но нету такого. При завершении приложения освобождаю мелочь - критические секции, и собственно, Indy - т.е. то, что создавалось при старте проги. А всё, что в процессе создаётся, в процессе же и уничтожаю... 
единственно, вот сюда приходит последняя переменная Resp.Body (TMemoryStream) которую я не уничтожаю - её по-идее должен инди освободить... все остальные стримы для этого потока, к этому моменту уже уничтожаются. 
Код
procedure TServer.Proxy_HTTPServerCommandGet(AContext: TIdContext;  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  FlatFile: TFlat;
  Resp: TResponse;
  FileType: byte;
begin
    if ARequestInfo.Host='localhost' then ARequestInfo.Host:=GCHost;

    try
        ActivateTimer;
        SplitToBeasyIcon(True);

        
        try

          FileType:=GE_FileType(ARequestInfo);

          case FileType of
           0..3: Resp:=GE_URL_Downlod(ARequestInfo);
           4:    Resp:=GEAuth_Downlod(ARequestInfo);
           5:    Resp:=dbRoot_Downlod(ARequestInfo);
           6:    Resp:=GEServer_Downlod(ARequestInfo);
           255:  Resp:=URL_Downlod(ARequestInfo);
          end;

          AResponseInfo.ResponseText:='';
          AResponseInfo.Server:='';

          AResponseInfo.Connection:='';
          AResponseInfo.ContentLength:=-1;
          AResponseInfo.RawHeaders.Text:='';
          if ContainsStr(Resp.Head,'Content-Type') then AResponseInfo.ContentType:='';

          AResponseInfo.CustomHeaders.Text:=Resp.Head;
          AResponseInfo.FreeContentStream:=true;                                            <- Indy должен сам уничтожить

          try
            
            if (Resp.Body<>nil) and (Resp.Body.Size<>0)  then
            AResponseInfo.ContentStream:=Resp.Body                                       <- последний стрим
            else
            begin
              AResponseInfo.RawHeaders.Text:='';
              if AnsNotFound then AResponseInfo.ResponseNo:=403
              else AResponseInfo.ResponseNo:=404;

              Resp.Body.Destroy;
              AResponseInfo.Server:='btfe';
              AResponseInfo.ContentType:='text/html';
              AResponseInfo.ContentText:='404: NOT FOUND';
            end


          except
             AResponseInfo.CustomHeaders.Text:='';
             AResponseInfo.ResponseNo:=404;
          end;

             AResponseInfo.FreeContentStream:=true;
        finally
          SplitToBeasyIcon(False);
        end;

    except on E: Exception do
      E.Message:='Proxy_HTTPServer_Error'+#13#10+E.Message;
    end;

end;



Это сообщение отредактировал(а) zedx - 18.5.2009, 22:07
PM MAIL   Вверх
zedx
Дата 18.5.2009, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Самое интересное, что диспетчер задач винды, не обращает внимание на то, что происходит очистка озушки и в Хронологии использования файла подкачки (хотя повторюсь - файл подкачки отключён) - такая ровная восходящая линия, до момента выбрасывания/зависания проги... причём сама винда и проги не тормозят ничуть, т.е. опреративка-то свободна. А вот запуск фотошопа, в момент когда прога выжрала всю виртуалку, обломился, с ошибкой фотошопа - Файл подкачки слишком мал, для завершения операции. Странно это. 
PM MAIL   Вверх
CodeMonkey
Дата 18.5.2009, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Да ничего странного у вас нет. У вас либо нет утечки, но ошибка в логике (kami пример указал), либо утечка не памяти, а, скажем, объектов ядра (пример: создавать и не освобождать HBITMAP).

Если первое - попробуйте захавать как можно больше памяти, потом сделать дамп выделения (в этом вам поможет FastMM). Ткните наугад в карту памяти - с хорошей вероятностью получите виновника неявной утечки.
Если второе - то кроме mem-leak используйте другие утилиты - профайлеры ресурсов.

А EL какая версия? Я помню там баг когда-то был с детектом mem-leak-ов. Попробуйте ещё под FastMM или обновите EL до 6.0.20.

Добавлено @ 23:34
Да, кстати, после того, как разберётесь с проблемой, выкиньте вот это: SetProcessWorkingSetSize(MainHandle, DWORD(-1), DWORD(-1));

Это сообщение отредактировал(а) CodeMonkey - 18.5.2009, 23:35


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
zedx
Дата 18.5.2009, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Экврика как раз 6.0.20.

Цитата(CodeMonkey @  18.5.2009,  23:27 Найти цитируемый пост)
Если второе - то кроме mem-leak используйте другие утилиты - профайлеры ресурсов

...новое для меня понятие, пошёл напрягать гугл smile
PM MAIL   Вверх
kami
Дата 19.5.2009, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



При наличии 15 вызовов VirtualAlloc потребление памяти от вызовов этой ф-и достигло высот в 18353952 байт.
На 18-м программа скончалась.
MemProof упрямо говорит, что проблема в выделении памяти.
А именно:
function PutFileToCache => X:=TSaveX.Create(true); // показывает пальцем сюда.

И гораздо больше - 
просто вызов из function PutFlatFile => PutFileToCache. // и сюда
Который, кстати, идет в двух местах этой процедуры.

Это сообщение отредактировал(а) kami - 19.5.2009, 00:09
PM MAIL WWW   Вверх
zedx
Дата 19.5.2009, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Цитата(kami @  19.5.2009,  00:06 Найти цитируемый пост)
MemProof упрямо говорит, что проблема в выделении памяти.А именно:function PutFileToCache => X:=TSaveX.Create(true); // показывает пальцем сюда.

т.е. поток не уничтожается?

вот этот класс
Код
TSaveX = class(TThread)
  private
    fTile: TBuf;
    fURL: string;
    fSize:int64;
    protected
      procedure Execute;override;
    public
      property Size:int64 read fSize write fSize;
      property URL:string read fURL write fURL;
      property Tile: TBuf read fTile write fTile;
  end;



и его процедура:
Код
procedure TSaveX.Execute;
var Xname,sURL:string;
id:integer;
Mem:TMemoryStream;
begin
    sURL:=URL;

    Mem:=TMemoryStream.Create;

    try
      Mem.Write(Tile,Size);
      Xname:=URLToXName(sURL);

      id:=dbxOpen(Xname);

      if ID<>-1 then
      begin
        EnterCriticalSection(dbxCache.FileSection[ID]);
        try
          dbXWrite(sURL,Mem,ID);
        finally
          LeaveCriticalSection(dbxCache.FileSection[ID]);
        end;
      end;
    finally
      Mem.Free;
    end;
end;



Это сообщение отредактировал(а) zedx - 19.5.2009, 00:18
PM MAIL   Вверх
kami
Дата 19.5.2009, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(zedx @  19.5.2009,  00:13 Найти цитируемый пост)
т.е. поток не уничтожается?

1. Пройдитесь отладчиком - я не могу скомпилировать код, т.к. не пользуюсь инди.
А ковырять чужой код... ладно бы минимальный тестовый пример, в котором проявляется ошибка, а полный код smile

2. Скачайте себе профайлер и посмотрите сами что да как.

PM MAIL WWW   Вверх
CodeMonkey
Дата 19.5.2009, 08:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Цитата(zedx @  18.5.2009,  23:46 Найти цитируемый пост)
...новое для меня понятие, пошёл напрягать гугл

Посмотрите это, это, это.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
zedx
Дата 20.5.2009, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Поставил AQTime v6.20, интегрировался он в проект. Выбираю подозрительный модуль (с точки зрения утечки), правый клик мышью -> Profile xxx.pas В настройках выбрал профиль Allocation Profile. Запускаю, гоняю, вижу утечку в Диспетчере задач, закрываю прогу. AQT выдаёт мне репорт:
Код
Object  Name    Size    Root    Address    References To    Get#
VCL native memory.89637    380    False    0x06F23C44    0    1
...
VCL native memory.91587    380    False    0x06F24AE4    0    1
VCL native memory.102037    380    False    0x06F25304    0    1
VCL native memory.117764    380    False    0x06F25B24    0    1
Reserved Virtual Memory.2838    4096    False    0x06DB0000    0    1
Committed Virtual Memory.2839    4096    False    0x06DB0000    0    1
Reserved Virtual Memory.132092    5242880    False    0x08910000    0    1
Reserved Virtual Memory.123108    5242880    False    0x08010000    0    1

Очень много строчек VCL native memory - но размер мизерный, а вот 2 последние строчки: Reserved Virtual Memory - по 5 Мб - я так понимаю, это и есть утечка, т.к. строчек Committed после не наблюдается?
Не понимаю, как перейти теперь по этой инфе (Address 0x08010000) в исходники, на конкретную строку/процедуру, где эта утечка происходит... Что делать? 
PM MAIL   Вверх
zedx
Дата 20.5.2009, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Похоже, что нашел основную утечку (правда, методом тыка - по-этапно исключая из кода то, что можно отключить. Как находить утечки с AQTime так и не выяснил). Виновником оказался визуальный компонент от TMS: AdvStringGrid. Я использую его для динамического добавления строк+раскраска (причём всё это происходит из потока).
Помогло исключение из кода строчек: 
Код

AdvStringGrid1.Rows[RowData.Number]:=RowString;
AdvStringGrid1.RowColor[RowData.Number]:=HexToTColor(ReadyCl);

... и как мне теперь, интересно, строки писать?




Это сообщение отредактировал(а) zedx - 21.5.2009, 12:56
PM MAIL   Вверх
kami
Дата 24.5.2009, 19:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(zedx @  20.5.2009,  23:11 Найти цитируемый пост)
причём всё это происходит из потока

Нехорошо обращаться к визуальным компонентам из потока.
Сделать это хотя бы из метода синхронизации потока.
Поэтому и могут идти утечки.

Цитата(zedx @  20.5.2009,  23:11 Найти цитируемый пост)
и как мне теперь, интересно, строки писать?

А исходный код компонентов доступен?

Добавлено через 1 минуту и 25 секунд
Цитата(zedx @  20.5.2009,  23:11 Найти цитируемый пост)
 Как находить утечки с AQTime так и не выяснил

Тоже не помогу.
Для этой цели использую исключительно FastMM, а AQ - для замера производительности сложных участков кода.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0583 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.