Страницы

Поиск по вопросам

суббота, 7 марта 2020 г.

Утечка памяти в TObjectList

#delphi


Не могу найти решение для устранении утечки.



type
  TMyObj = class
  Caption: string;
  Description: string;
  Params:string;
  ParamsLst: TStringList;

public
  constructor Create(const aPath: string; const aParams: TStrings); overload;
  destructor Destroy(); override;
end;

TDataList = class(TObjectList)
public
  constructor Create;
  // function LoadFromINI(IniFile: TMemIniFile): boolean;
  function Remove(Obj: TMyObj): Integer;
end;

var
  TObjData: TDataList;

implementation

constructor TMyObj.Create(const aPath: string; const aParams: TStrings);
begin
  Caption := aParams.Values['Caption'];
  Description := aParams.Values['Description'];
  Params := aParams.Values['Params'];
  if aParams.Values['Params'] <> '' then
  begin
    ParamsLst := TStringList.Create;
    try
      ExtractStrings([';', ','], [' '], PChar(Params), ParamsLst);
    except
      ParamsLst := nil;
    end;
  end;
end;

destructor TMyObj.Destroy;
begin
  ParamsLst.Free;
  inherited;
end;

constructor TDataList.Create;
begin
  inherited Create;
  OwnsObjects := True;
end;

function TDataList.Remove(Obj: TMyObj): Integer;
begin
  Result := inherited Remove(Obj);
end;

initialization
TObjData := TDataList.Create;

finalization
TObjData.Free;


заполнение TObjData, так

    TObjData.Add(TMyObj.Create(sVal, SecParams));

    


Ответы

Ответ 1



Что касается исключения - точное место создания объекта, который не уничтожился может показать FastMM или EurekaLog. Приведенный код рабочий и в большинстве случаев все правильно освобождается. (Нюансы описал ниже.) Скорее всего вы создается TreeList и его не уничтожаете (либо ждете что его уничтожит родительский объект, а он не назначен). Остальные нюансы: Может я что то упустил, но я не вижу откуда берутся данные для заполнения SecParams. Если вы до момента добавления создали SecParams - его нужно уничтожить. Иначе будет утечка. TObjData.Add(TMyObj.Create(sVal, SecParams)); Второй участок try..except. При возникновении исключения - объект все же не уничтожится. ParamsLst := TStringList.Create; try ExtractStrings([';', ','], [' '], PChar(Params), ParamsLst); except ParamsLst := nil; // end; Хотя тоже не ясно, ну не обработались параметры, значит они в неправильном формате - объект создастся, но с пустым параметром ParamsLst. И если к нему обратится без проверки - будет Access Violation. TObjData - есть общие правила когда с буквы T начинаются описания типов. F - для внутренних полей класса. var TObjData: TDataList; Для полей класса TMyObj нужно явно указать идентификатор видимости (private, public), а еще лучше перенести их в секцию private и дать доступ к полям с помощью свойств. Например: type TMyObj = class FCaption: string; public ... property Caption: string read FCaption; end; TMyObj - название класса должно описывать объект. (Например: TPerson)

Ответ 2



В коде нет ни одного момента заполнения переменной со странным именем TObjData. Но могу предположить, что OwnsObjects не правильно срабатывает. В финализации перед разрушением объекта TObjData лучше сделать цикл проверки вложенных в него объектов и выяснения по какой причине они не освобождаются до финализации.

Ответ 3



Код с учетом замечаний и предложений...... type TData = class private FCaption: string; FDescription: string; FParams: string; FParamsLst: TStringList; //.... public constructor Create(const aPath: string; const aParams: TStrings); destructor Destroy(); override; property Caption: string read FCaption; property Description: string read FDescription; property Params: string read FParams; property ParamsLst: TStringList read FParamsLst; //... end; TDataList = class(TObjectList) private //... public constructor Create; destructor Destroy(); override; property //... end; var DataList: TDataList; implementation { TData } constructor TData.Create(const sPath: string; const sData: TStrings); begin Caption := aParams.Values['..']; Description := aParams.Values['..']; Params := aParams.Values['..']; if aParams.Values['..'] <> '' then begin ParamsLst := TStringList.Create; try ExtractStrings([','], [' '], PChar(Params), ParamsLst); except on E: Exception do ShowMessage(E.ClassName + ': ' + E.Message); end; end; end; destructor TData.Destroy; begin inherited; end; { end TData } { DataList } constructor TDataList.Create; begin inherited Create; OwnsObjects := True; end; destructor TDataList.Destroy; begin inherited; end; { end DataList } Решение, проблемы ...... procedure TMain.FormDestroy(Sender: TObject); var I: Integer; begin // Удаление списков в объекте for i := 0 to DataList.Count - 1 do begin with DataList.Items[i] do begin ParamsLst.Free; end; end; // При удалении списка оставшиеся в нём объекты будут удалены. FreeAndNil(DataList); end;

Комментариев нет:

Отправить комментарий