Какие существуют методы автоматического удаления объектов в приложениях delphi?
Как автоматически освобождать классы/объекты?
Ответ 1
Используйте интерфейсы вместо объектов. Они подсчитываются и освобождаются автоматически, когда количество ссылок достигает 0.
Ответ 2
Я написал функцию GC (obj: TObject) (для Garbage Collect), которая берет объект и освобождает его, когда выполнение оставляет текущий метод. Это похоже на однострочную сокращенную функцию для блока Try finally Free.
Вместо:
procedure Test;
var AQuery: TQuery;
begin
AQuery := TQuery.Create(nil);
try
...
finally
FreeAndNil(AQuery);
end;
end;
У меня только:
procedure Test;
var AQuery: TQuery;
begin
AQuery := TQuery.Create(nil);
GC(AQuery);
...
end;
Функция GC просто возвращает объект в виде интерфейса.
function GC(obj: TObject): IGarbo;
begin
Result := TGarbo.Create(obj);
end;
Поскольку класс TGarbo спускается из TInterfacedObject, когда объект TGarbo выходит из области видимости, он автоматически освобождается. В деструкторе объекта TGarbo он также освобождает объект, который вы передали ему в его конструкторе (объект, который вы передали в функции GC).
type
IGarbo = interface
['{A6E17957-C233-4433-BCBD-3B53C0C2C596}']
function Obj: TObject;
end;
TGarbo = class(TInterfacedObject, IGarbo)
private
FObj: TObject;
public
constructor Create(AObjectToGC: TObject);
destructor Destroy; override;
function Obj: TObject;
end;
{ TGarbo }
constructor TGarbo.Create(AObjectToGC: TObject);
begin
inherited Create;
FObj := AObjectToGC;
end;
destructor TGarbo.Destroy;
begin
if Assigned(FObj) then
FreeAndNil(FObj);
inherited;
end;
function TGarbo.Obj: TObject;
begin
Result := FObj;
end;
Будучи застрявшим в мире Delphi 7 без видимых улучшений до версии Delphi со встроенной сборкой мусора в ближайшем будущем, я пристрастился к использованию этого короткого метода легкого освобождения локальных временных объектов!:)
Ответ 3
В линейках интерфейсов вы можете попробовать функцию Guard
в модуле JclSysUtils
, являющуюся частью бесплатной Jedi Code Library, Это позволяет связать объект с отдельной ссылкой на интерфейс, поэтому, когда эта ссылка на интерфейс уничтожена, объект уничтожается вместе с ним. Это может быть полезно, если у вас нет возможности изменять классы, которые вы используете, чтобы заставить их поддерживать собственные интерфейсы.
var
G: ISafeGuard;
foo: TStrings;
begin
// Guard returns TObject, so a type-cast is necessary
foo := Guard(TStringList.Create, G) as TStrings;
// Use the object as normal
foo.Add('bar');
end; // foo gets freed automatically as G goes out of scope
Существуют перегрузки для объектов и GetMem
-распределенные указатели. Существует также IMultiSafeGuard
, который может гарантировать освобождение нескольких объектов.
Если у вас есть функция factory, вы можете создать объект, установить некоторые его свойства и затем вернуть его. Если при настройке свойств возникает исключение, вы должны убедиться, что вы освобождаете объект, так как вы не можете его вернуть. Один из способов сделать это:
function Slurp(const source: TFileName): TStrings;
begin
Result := TStringList.Create;
try
Result.LoadFromFile(source);
except
Result.Free;
raise;
end;
end;
С Guard
он станет следующим:
function Slurp(const source: TFileName): TStrings;
var
G: ISafeGuard;
begin
Result := Guard(TStringList.Create, G) as TStrings;
Result.LoadFromFile(source);
G.ReleaseItem;
end;
Метод ReleaseItem
отменяет право собственности на объект ISafeGuard
. Если произойдет исключение до того, как это произойдет, тогда, когда пакет распанется и освободится интерфейс, защитник освободит объект.
Ответ 4
Используйте принадлежность объекта к компонентам, которые предоставляет VCL. Пока вы создаете объекты с владельцем не-nil, вам не нужно их бесплатно освобождать. См. Также мой ответ на этот вопрос.
Ответ 5
Я должен сказать, мне не нравится "скрывать" Свободный объект. Гораздо лучше иметь традиционный код:
MyObject := TObject.Create;
try
// do stuff
finally
FreeAndNil(MyObject);
end;
Ни в коем случае это может пойти не так, работает, как ожидалось, и люди узнают шаблон.
Ответ 6
Ниже приведена API для DLL Boemm Garbage Collector для Delphi. API Delphi написан Барри Келли, который работает для CodeGear, пишущего компилятор.
Ответ 7
Умные указатели работают очень хорошо, если у вас есть Delphi 2009.
Ответ 8
Если вы используете Delphi для .Net/Delphi Prism, вы получаете Garbage Collection, которая заботится обо всех освобождениях.