I implemented the following class:
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;
Then I have a global variable:
procedures: TDictionary<string, TCallback>;
In OnFormActivate procedure I initalize the procedures variable:
procedures := TDictionary<string, TCallback>.Create();
procedures.Add('something', TCallback.Create('sth', @proc, 'annotation'));
// ....
And then in OnFormClose I free it:
procedures.Clear;
procedures.Free;
Does my code leak memory? If so what is the correct way to free the dictionary?
From what I know iteration is not good idea.
The code leaks memory because the objects contained in a
TDictionaryare not automatically freed.If you need to store objects in a dictionary, the adoption of a TObjectDictionary represents a better approach.
If you want the objects contained in the dictionary to be automatically freed, use the
doOwnsValuesflag while creating the instance of the collection.When the variable is really global (i.e. is declared under
varin theinterfacesection of the unit), it should be created and destroyed in theinitializationandfinalizationsection of the unit itself.When your variable belongs to the form class itself, you should create the dictionary in the form's
OnCreateevent.Free the dictionary in the form's
OnDestroyevent:Furthermore, if you want the variable belonging to the class to be accessed without the need of an instance of the class itself (this is referred as a static variable in many programming languages), you can declare the dictionary as a
class varand optionally access it through aclass property; in such a case, it's better to create and destroy the collection in theclass constructorand in theclass destructor.As a side note, the
TCallbackclass does not need to specify a destructor because only owns two strings and a pointer to a procedure. And so the default destructor inherited fromTObjectsuffices.