如果我有一个指向内存的指针,我该如何判断它是否指向一个基于堆的结构(并因此应该被释放)还是指向堆栈(因此不应该被触摸)?如何判断指针是指向堆栈还是指向堆?
下面是一些示例代码。
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