관리되는 유형은 참조가 계산되고 계수가 0으로 떨어지면 완료됩니다. 지역 변수가 있으면 범위를 벗어나면 참조 카운트가 0으로 떨어집니다.
따라서 인터페이스를 사용하여 참조하는 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;
당신은 다음과 같이 사용할 수는 :
LifetimeWatcher
이 범위를 잎
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;
, 당신은 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;
문자열이 스택에 없습니다. 이들은 힙에 대한 참조 카운트 포인터입니다. –
알아요.하지만 어떻게 풀려나나요? –
참조 계산 메커니즘으로 - 일단 0이면 메모리가 해제됩니다. 이것은 문자열 및 동적 배열에 대해 컴파일러에서 관리합니다. 귀하의 질문에 대한 가능한 해결책은 동적 인'바이트 배열 (array of byte) '을 사용하는 것입니다. 나중에 (2009+?) 델파이 버전에서는 TBytes로 미리 정의되어 있습니다 (http://docwiki.embarcadero.com/Libraries/XE4/en/System .SysUtils.TBytes) –