Delphi → Утечка памяти в IEnumVARIANT

Май 11, 2011


При работе с перечислениями IEnumVARIANT было замечено странное поведение - каждая итерация с получением следующего элемента IEnumVARIANT.Next приводила к увеличению размера в памяти, занимаемого приложением. После каждых 1000 итераций размер увеличивался на 2 Мб, а это очень критично когда программа должна работать продолжительное время.

Это как раз мой случай, т.к. я разрабатывал сервис, который постоянно запущен, даже если пользователь не зашел в систему под своими учетными данными. Данная утечка могла бы к концу дня полностью повесить систему, поэтому в течении нескольких часов я кропотливо проверял каждую строчку своего кода, дабы найти эту утечку. Путем перебора было определено, что утечку дает, как я уже говорил, функция IEnumVARIANT.Next. Например, в следующем листинге представлен код с утечкой:

uses
  SysUtils, ActiveX;

var
  FEnum: IEnumVARIANT;
  FVariant: OleVariant;
  FCount: Cardinal;
  FIndex: integer;

begin
  FIndex := 0;
  while (true) do
  begin
    if FEnum.Next(1, FVariant, FCount) <> S_OK then Break; // Здесь утечка
    Inc(FIndex);
  end;
  WriteLn(IntToStr(FIndex));
  FEnum := nil; // Используйте вместо метода _Release
end.


Когда происходит второй вызов функции Next и при этом переменная FVariant (OleVariant) содержит какое-либо значение, происходит утечка. Предыдущее значение FVariant не затирается, а остается в памяти. Поэтому, перед тем как производить запись в FVariant, нужно очистить эту переменную. Исправленная версия кода (без утечки) будет выглядеть так:

uses
  SysUtils, ActiveX, Variants;

var
  FEnum: IEnumVARIANT;
  FVariant: OleVariant;
  FCount: Cardinal;
  FIndex: integer;

begin
  FIndex := 0;
  while (true) do
  begin
    if not VarIsNull(FVariant) then FVariant := Unassigned; // Обнуление переменной
    if FEnum.Next(1, FVariant, FCount) <> S_OK then Break; // Утечки больше нет
    Inc(FIndex);
  end;
  WriteLn(IntToStr(FIndex));
  FEnum := nil;
end.
Это лето выдалось достаточно жарким и знойным, даже работать не хочется в такую жару. Как поговаривал мой дед - "Ноги нужно держать в тепле, а голову в холоде". Благо в офисе у нас стоит кондер и охлаждает помещение. Обидно только, что дома нет кондиционера и даже вентилятор не спасает. Вот бы собрать все кондиционеры Перми в моей квартире, да включить их на пару часиков, и тогда уж точно по квартире можно будет на коньках кататься.

Post to Twitter

Похожие статьи:

  1. Количество элементов в IEnumVARIANT
  2. Компоненты в массиве TObjectList
  3. Многопоточность в Delphi
  4. Ускоритель SQLite запросов

Нет комментариев

Ваш комментарий

Rambler's Top100 Яндекс.Метрика