託管類型的引用已計數,當計數降至零時,它們即已完成。如果您有一個局部變量,那麼當它超出範圍時,其引用計數將降爲零。
所以,你可以創建一個TInterfacedObject
的後代,你使用的是一個接口。事情是這樣的:
type
TLifetimeWatcher = class(TInterfacedObject)
private
FDestroyProc: TProc;
public
constructor Create(const DestroyProc: TProc);
destructor Destroy; override;
end;
constructor TLifetimeWatcher.Create(const DestroyProc: TProc);
begin
inherited Create;
FDestroyProc := DestroyProc;
end;
destructor TLifetimeWatcher.Destroy;
begin
if Assigned(FDestroyProc) then
FDestroyProc();
inherited;
end;
然後,您可以使用它像這樣:
procedure MyProcedure;
var
MyPointer: Pointer;
LifetimeWatcher: IInterface;
begin
MyPointer := VirtualAlloc (NIL, 1024, MEM_COMMIT or MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
LifetimeWatcher := TLifetimeWatcher.Create(
procedure
begin
VirtualFree(MyPointer, 0, MEM_RELEASE);
end;
)
FillMemory(MyPointer);
end;
當LifetimeWatcher
葉範圍,則執行被破壞,你傳遞給TLifetimeWatcher.Create
實現對象和程序。
將專門研究這個想法專門用於您的用例將會很容易。這將使呼叫站點的代碼更加簡潔。
這將是這樣的:
function VirtualAllocAutoRelease(Size: SIZE_T; Protect: DWORD;
out LifetimeCookie: IInterface): Pointer;
var
Ptr: Pointer;
begin
Ptr := VirtualAlloc(nil, Size, MEM_COMMIT or MEM_RESERVE, Protect);
Win32Check(Ptr<>nil);
LifetimeCookie := TLifetimeWatcher.Create(
procedure
begin
VirtualFree(Ptr, 0, MEM_RELEASE);
end
);
Result := Ptr;
end;
你會使用這樣的:
procedure MyProcedure;
var
MyPointer: Pointer;
LifetimeWatcher: IInterface;
begin
MyPointer := VirtualAllocAutoRelease(1024, PAGE_EXECUTE_READWRITE,
LifetimeWatcher);
FillMemory(MyPointer);
end;
字符串不在堆棧中。它們是一個引用計數指向堆的指針。 –
我知道,但他們如何獲得釋放? –
通過引用計數機制 - 一旦它爲零,內存就被釋放。這由編譯器對字符串和動態數組進行管理。一個可能的解決方案是在後來的(2009+?)Delphi中使用一個動態的'byte數組',它被預定義爲TBytes(http://docwiki.embarcadero.com/Libraries/XE4/en/System .SysUtils.TBytes) –