FastMM4说"块头已被破坏"

WeG*_*ars 5 delphi delphi-7 fastmm memory-corruption

我有这个令人讨厌的虫子在过去消失了,但现在经过一段时间它又回来了.

我有两个TSam对象(派生自TPersistent)创建并加载到TAsmJob对象(从TObjectList派生).

在运行时,表单创建一个TStringGrid,然后创建AsmJob,它创建这两个SAM对象(并从每个对象的磁盘加载一些数据).AsmJob也被分配给网格.当表单被销毁时,Grid通过释放它来处理AsmJob,从而释放TSam对象.这是问题所在:第一个对象没有问题,但第二个对象在调用其继承方法(在Destroy析构函数中)时会死掉.

我在整个程序中使用FreeAndNil来释放对象.TSam对象不是NIL !!!!! 所以,这是第一次释放对象的尝试.甚至对象内部的数据也是一致的.

该计划的主干如下:

**Create:**

Form -> StringGrid
     -> AsmJob -> Sam1, Sam2
StringGrid.AsmJob:= AsmJob;


**Free:**

Form -> StringGrid -> AsmJob -> Sam1, Sam2
Run Code Online (Sandbox Code Playgroud)

我真的不明白在它被释放后我试图双重释放或覆盖对象的位置.


编辑:

我得到的一些错误:

  • 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]  
Run Code Online (Sandbox Code Playgroud)

我在IDE中启用了所有"调试"选项,包括"范围检查".此外,FastMM4设置为超级激进的调试模式.如果没有FastMM或者在调试器之外,程序运行得很好 - 但我知道这并不意味着错误不再存在.实际上它(可能)工作了一年多,直到我安装了FastMM.


编辑:

感谢大家.不,我感觉我正朝着好的方向前进.

程序的结构更复杂我只提供了保持原始帖子小的骨干.但是,它已经变大了:)所以,那些TSam对象用于从磁盘加载数据.每个对象中有一个文件.他们还在进行一些处理和数据验证.对于这些TSam中的每一个,我还有一个图形对象,在屏幕上(图形地)显示TSam对象中包含的数据.TStringGrid中的每一行也以TSam显示数据,但是以文本方式显示.

我有一个问题:如果我以较小的碎片打破程序以找出错误的位置,错误仍会出现?或者只能在此特定配置中出现?


回答"如何将AsmJob分配给TStringGrid,以便TStringGrid破坏AsmJob,你能告诉我们吗?"

MyGrid = TStringGrid
  public 
    AsmJob: TAsmJob; 
  end; 
Run Code Online (Sandbox Code Playgroud)

然后在TForm.Create(保存网格的形式)的某个地方,我这样做

MyGrid.AsmJob=AsmJob; 
Run Code Online (Sandbox Code Playgroud)

在我的MyGrid的析构函数中:

begin 
  FreeAndNil(AsmJob); 
  inherited 
end;
Run Code Online (Sandbox Code Playgroud)

Ale*_*lex 14

此错误意味着您的代码损坏了内部内存管理器的结构.当MM检测到这个时,你的调用堆栈代表点.这不是错误路径或与之相关的任何内容.实际错误发生在此刻之前.它可能与提到的类有关,也可能没有关系.

您应该尝试在完全调试模式下使用"范围检查错误"选项(不要忘记进行构建,而不是编译)和FastMM(启用CheckHeapForCorruption,CatchUseOfFreedInterfaces和DetectMMOperationsAfterUninstall选项).

您还可以打开FullDebugModeScanMemoryPoolBeforeEveryOperation全局变量,在问题发生后几乎立即得到错误,但是此选项会减慢执行速度A LOT.

可能最好的选择是定期调用ScanMemoryPoolForCorruptions.在一个地方叫它.出了错误?马上打电话吧.仍有错误?再打电话吧.没错误?你的问题介于最后一次通话之间.现在,您可以使用FullDebugModeScanMemoryPoolBeforeEveryOperation变量来获取精确位置.只需在此代码区域打开它,然后立即将其关闭.

有一个非常类似的错误:"FastMM在被释放后检测到块已被修改".在这种情况下,您的代码不会修改内部结构,而是修改根本不使用的其他内存("可用内存").

顺便说一下,你的错误不是双重的!如果这是一个双重免费调用,FastMM会明确告诉你(很容易检测到,因为你试图释放未使用或不存在的内存块):"已尝试释放/重新分配未分配的块".