Delphi словарь освобождает
Я реализовал следующий класс:
type
TUtilProcedure = procedure(var AJsonValue: TJSONObject);
TCallback = class
private
FName: string;
FProcedure: TUtilProcedure;
FAnnotation: string;
public
constructor Create(AName: string; AProcedure: TUtilProcedure; AAnnotation: string); overload;
constructor Create(ACallback: TCallback); overload;
property Name: string read FName;
property Proc: TUtilProcedure read FProcedure;
property Annotation: string read FAnnotation;
end;
Тогда у меня есть глобальная переменная:
procedures: TDictionary<string, TCallback>;
В OnFormActivate
процедура я инициализирую procedures
переменная:
procedures := TDictionary<string, TCallback>.Create();
procedures.Add('something', TCallback.Create('sth', @proc, 'annotation'));
// ....
А потом в OnFormClose
Я освобождаю это:
procedures.Clear;
procedures.Free;
Мой код пропускает память? Если да, то как правильно освободить dictionary
? Из того, что я знаю, итерация не очень хорошая идея.
1 ответ
Код утечки памяти, потому что объекты, содержащиеся в TDictionary
не освобождаются автоматически
Если вам нужно хранить объекты в словаре, принятие TObjectDictionary представляет собой лучший подход.
Если вы хотите, чтобы объекты, содержащиеся в словаре, были автоматически освобождены, используйте doOwnsValues
флаг при создании экземпляра коллекции.
Когда переменная действительно глобальная (т.е. объявлена в
var
вinterface
раздел блока), он должен быть создан и уничтожен вinitialization
а такжеfinalization
раздел самого блока.. . . var procedures: TObjectDictionary<string, TCallback>; . . . initialization procedures:= TObjectDictionary<string, TCallback>.Create([doOwnsValues]); finalization procedures.Free;
Когда ваша переменная принадлежит самому классу формы, вы должны создать словарь в форме
OnCreate
событие.. . . public procedures: TObjectDictionary<string, TCallback>; . . . procedure TForm1.FormCreate(Sender: TObject); begin procedures:= TObjectDictionary<string, TCallback>.Create([doOwnsValues]); end;
Бесплатный словарь в форме
OnDestroy
событие:procedure TForm1.FormDestroy(Sender: TObject); begin procedures.Free; end;
Кроме того, если вы хотите, чтобы к переменной, принадлежащей классу, обращались без необходимости экземпляра самого класса (это называется статической переменной во многих языках программирования), вы можете объявить словарь как
class var
и при желании получить к нему доступ черезclass property
; в таком случае лучше создать и уничтожить коллекцию вclass constructor
и вclass destructor
,. . . TMyClass = class private class constructor Create; class destructor Destoy; public class var procedures: TObjectDictionary<string, TCallback>; end; . . . class constructor TMyClass.Create; begin procedures := TObjectDictionary<string, TCallback>.Create([doOwnsValues]); end; class destructor TMyClass.Destoy; begin procedures.Free; end;
TCallback = class
private
FName: string;
FProcedure: TUtilProcedure;
FAnnotation: string;
public
constructor Create(AName: string; AProcedure: TUtilProcedure; AAnnotation: string); overload;
constructor Create(ACallback: TCallback); overload;
property Name: string read FName;
property Proc: TUtilProcedure read FProcedure;
property Annotation: string read FAnnotation;
end;
Как примечание стороны, TCallback
В классе не нужно указывать деструктор, потому что он владеет только двумя строками и указателем на процедуру. И поэтому деструктор по умолчанию унаследован от TObject
достаточно.