我曾经遇到过一个很讨厌的错误,它在过去消失了,但现在又回来了。
我有两个TSam对象(派生自TPersistent),并被创建和加载到TAsmJob对象(派生自TObjectList)中。
在运行时,一个窗体创建了一个TStringGrid,然后创建了AsmJob,该作业创建了这两个SAM对象(并从磁盘中加载了一些数据)。 AsmJob也分配给了网格。 当窗体被销毁时,网格会通过释放AsmJob来处理它,这将释放TSam对象。 这里出现了问题:第一个对象没有问题地释放了,但是当调用其继承方法(在Destroy析构函数中)时,第二个对象就死了。
我在整个程序中使用FreeAndNil来释放对象。 TSam对象不是NIL! 因此,这是释放对象的第一次尝试。 即使对象内部的数据也是一致的。
程序的主要结构如下:
**Create:**
Form -> StringGrid
-> AsmJob -> Sam1, Sam2
StringGrid.AsmJob:= AsmJob;
**Free:**
Form -> StringGrid -> AsmJob -> Sam1, Sam2
我真的不明白在对象被释放后我试图进行双重释放或覆盖的地方在哪里。
编辑:
我遇到的一些错误:
FastMM 在执行空闲块扫描操作期间检测到错误。FastMM 检测到一个块在被释放后已被修改。
FastMM 在执行空闲块扫描操作期间检测到错误。块头已经损坏。
详情:
The current thread ID is 0x19C, and the stack trace (return addresses) leading to this error is:
402E77 [System][@FreeMem]
4068DC [System][@DynArrayClear]
405E2D [System][@FinalizeArray]
405D31 [System][@FinalizeRecord]
40432F [System][TObject.CleanupInstance]
404272 [System][TObject.FreeInstance]
404641 [System][@ClassDestroy]
4D313E [UnitSam.pas][TSam.Destroy][297]
4042BF [System][TObject.Free]
4149ED [SysUtils][FreeAndNil]
4D9C0A [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180]
我已经在IDE中启用了所有的“调试”选项,包括“范围检查”。另外,FastMM4被设置为超级严格的调试模式。没有FastMM或者在调试器之外运行时,程序运行得很好 - 但我知道这并不意味着错误不再存在。实际上,它(可能)已经运行了一年以上,直到我安装了FastMM。
编辑:
谢谢大家。现在我感觉我正在朝着正确的方向前进。
程序的结构比较复杂,我只提供了骨干内容以使原帖保持简短。但是,算了,它已经变得更长了 :) 所以,这些TSam对象用于从磁盘加载数据。每个对象对应一个文件。它们还执行一些处理和数据验证。对于每个TSam对象,我还有一个图形对象,以图形方式显示屏幕上的数据。TStringGrid中的每一行也以文本方式显示TSam中的数据。
我有一个问题:如果我将程序分解成更小的部分以找出错误在哪里,这个错误仍然会出现吗?还是可能仅在特定配置中出现?
回答“如何将AsmJob分配给TStringGrid,以使TStringGrid销毁AsmJob,你能给我们展示吗?”
MyGrid = TStringGrid
public
AsmJob: TAsmJob;
end;
然后在 TForm.Create 中(这个窗体包含了 Grid),我执行以下操作
MyGrid.AsmJob=AsmJob;
在 MyGrid 的析构函数中,我执行以下操作:
begin
FreeAndNil(AsmJob);
inherited
end;