如果我有一個指向內存的指針,我該如何判斷它是否指向一個基於堆的結構(並因此應該被釋放)還是指向堆棧(因此不應該被觸摸)?如何判斷指針是指向堆棧還是指向堆?
下面是一些示例代碼。
TMiniStack<T> = record
private
SP: integer;
fData: array[0..DefaultStackSize - 1] of T;
public
procedure Free;
procedure Push(const Item: T); inline;
function Pop: T; inline;
end;
StaticFactory<T> = class
public type
PStack = ^Stack;
Stack = TMiniStack<T>;
public
class function Create(Size: integer = DefaultStackSize); static;
end;
implementation
我怎麼把在Free
「析構函數」的斷言,使登錄嘗試釋放一個基於堆棧的堆棧?
procedure TMiniStack<T>.Free;
begin
AssertOrLog(@Self is really on the heap,'This stack does not live on the heap');
Finalize(Items, Count);
FreeMemory(@Self);
end;
我似乎記得有一個IsValidPointer
方法。但找不到任何文檔。
我希望能夠區分堆棧/堆錯誤和其他指針問題。
編輯:Choosen解決方案
要調試幫助我添加了一個IsHeapBased: TGUID
場。只有在定義了調試的情況下才會包含此信息自由方法中的斷言檢查並提供反饋。我還添加了一個容量字段(僅調試)來檢測堆棧溢出。
這種檢查的目的僅僅是爲了幫助調試。
{$IFDEF DEBUG}
MagicHeapFlag: TGUID = '{EF227045-27A9-4EF3-99E3-9D279D58F9A0}';
{$ENDIF}
class function MiniStack<T>.Create(Size: integer = DefaultSize): PStack;
begin
Result:= AllocMem(SizeOf(TMiniStack<T>) - (DefaultSize * SizeOf(T)) + (Size * SizeOf(T)));
Result.SP:= 0;
{$IFDEF DEBUG}
Result.IsHeapBased:= MagicHeapFlag;
Result.HeapSize:= Size;
{$ENDIF}
end;
{$IFDEF DEBUG}
function TMiniStack<T>.capacity: Integer;
begin
if IsHeapBased = MagicHeapFlag then begin
Result:= HeapSize;
end
else Result:= DefaultSize;
end;
{$ENDIF}
procedure TMiniStack<T>.Free;
begin
{$IFDEF DEBUG}
Assert(IsHeapBased = MagicHeapFlag, 'Do not call free on stack based MiniStacks');
{$ENDIF}
Finalize(Items, count);
FreeMem(@Self);
end;
如果你知道你的最大堆棧大小,你可以使用這樣的東西:http://stackoverflow.com/a/2741560/327083看看你在哪裏,然後確定地址是否在當前堆棧的範圍內。同意@DavidHeffernan記住你,這似乎是一個可疑實用程序的練習... – 2014-08-28 21:45:22
@J ...並非所有棧都有相同的大小 – 2014-08-29 07:40:27
FreeMemory不是處理動態分配記錄的正確方法。應該使用例程「Dispose」來代替。 – 2014-08-29 14:13:22