昨天我发生了一些内存损坏,我非常怀疑某些记录数组是如何被分配和解除分配的。这是演示的简短版本:
type
TMyRecord = record
W: word;
S: String;
end;
TMyRecordArray = array [1 .. 315] of TMyRecord;
TArrayPointer = ^TMyRecordArray;
var
PageBase: TArrayPointer;
procedure TTestForm.FormCreate(Sender: TObject);
var
iRecord: TMyRecord;
begin
PageBase := AllocMem(SizeOf(TMyRecordArray));
iRecord.W := 1;
iRecord.S := 'TEST';
PageBase^[1] := iRecord;
end;
procedure TTestForm.FormDestroy(Sender: TObject);
begin
PageBase^[1] := Default (TMyRecord);
FreeMem(TPageBase);
end;
我很确定我没有做到这一点,任何建议都会受到赞赏。
答案 0 :(得分:8)
首先要说的是你提出的代码是有效的。它在没有泄漏的情况下正确地完成并解除分配。所以我会更广泛地回答你的问题。
字符串是托管类型,编译器需要使用特殊的内存分配例程来管理它们:New
和Dispose
。
分配
New(PageBase);
并取消分配:
Dispose(PageBase);
对New
的调用可确保管理的所有成员都是默认初始化的。另一方面,Dispose
将最终确定任何管理成员。
您可以在代码尝试时手动执行此操作。但在实际代码中,您需要最终确定数组的每个元素。您的代码只能完成一个。当然,它也只初始化一个,并且在问题中写的很好。也许你的问题的简短版本已经简化到目前为止已经删除了错误。
但是,我当然不建议您手动处理托管类型。请使用New
和Dispose
。
值得一提的是,动态数组在这里会简单得多。使用动态数组可以让编译器负责所有的分配和释放,并正确处理任何托管类型。