[英]Automatically free memory when leaving stack
我想编程一些有助于我在动态分配的地址空间的指针离开堆栈后自动释放内存的东西。 一个例子是:
procedure FillMemory (var mypointer);
begin
// CopyMemory, Move, etc... with data
end;
procedure MyProcedure;
var
MyPointer : Pointer;
begin
MyPointer := VirtualAlloc (NIL, 1024, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
FillMemory (MyPointer);
VirtualFree(MyPointer, 0, MEM_RELEASE); // I would like to avoid this...
end;
我可以使用字符串,但我也想避免使用它们(我不确定堆栈中的字符串是否会被释放...)有什么想法吗?
为了扩大我对Arioch的评论和讨论,
如果只需要原始内存块,请使用array of byte
的动态array of byte
。 编译器将在方法结束时生成代码以释放此内存:
type
TBytes = array of Byte; // omit for newer Delphi versions
procedure FillMemory(var Bytes: TBytes);
begin
{ passing in here will increase the reference count to 2 }
// CopyMemory, Move, etc... with data
end; // then drop back to 1
procedure MyProcedure;
var
Buffer : TBytes;
begin
SetLength(Buffer, 1024); // buffer has reference count of 1
FillMemory (Buffer);
end; // reference count will drop to 0, and Delphi will free memory here
希望这一切都有道理。 现在是午夜,所以我没有最清醒的感觉...
托管类型对其引用进行计数,当计数降至零时,它们将被确定。 如果您有局部变量,则当其超出范围时,其引用计数将降至零。
因此,您可以使用接口创建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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.