FastMM4 says “The block header has been corrupted”

╄→尐↘猪︶ㄣ 提交于 2019-12-03 03:44:53

This error means that your code corrupted internal memory manager's structures. Your call stack represents point, when MM detected this. This is not error path or anything related to it. The actual error happens BEFORE this moment. It may or may be not related to mentioned classes.

You should try to use "Range check errors" option (don't forget to make Build, not Compile) and FastMM in full debug mode (with CheckHeapForCorruption, CatchUseOfFreedInterfaces и DetectMMOperationsAfterUninstall options enabled).

You can also turn on FullDebugModeScanMemoryPoolBeforeEveryOperation global variable, to get an error almost immediately after problem occurs, but this option slows down your execution A LOT.

Probably the best choice is call ScanMemoryPoolForCorruptions periodically. Call it in one place. Got an error? Call it sooner. Still got an error? Call it sooner again. No error? Your problem sits somewhere between those last calls. Now you can use FullDebugModeScanMemoryPoolBeforeEveryOperation variable to get precise location. Just turn it on only on this code's area and turn it off right after it.

There is a very similar error: "FastMM detected that a block has been modified after being freed". In this case your code modifies not internal structures, but other memory, which isn't used at all ("free memory").

BTW, your error is NOT double-free! If this is a double-free call, FastMM will tell you that explicitly (it is easy to detect, as you are trying to free not-used or not-existed memory block): "An attempt has been made to free/reallocate an unallocated block".

A block header getting corrupted usually means something's been overwriting memory, usually by doing some sort of unsafe operation. Are you using raw pointers or assembly code in any of your tasks? Also, if you have range checking and bounds checking turned off, try turning them on and rebuilding. They can help catch a lot of this sort of problem.

There might be a logic race somewhere in the code where an object is being written to as it's being freed. Add NULL-checks and other IPC mechanisms (lock lists etc) to make sure that isn't the case.

Another option could be to subclass the code to add logging to it - and check whether objects are being sequentially accessed.

A couple of things and I'm asking because I can't see your code.

Given the following code:

procedure TForm1.FormCreate(Sender: TObject);
var
   wObjLst : TObjectList;
begin
   wObjLst := TObjectList.Create;
   try
      wObjlst.OwnsObjects := true;
      wObjlst.Add(TPersistent.Create);
      wObjlst.Add(TPersistent.Create);
   finally
      freeandnil(wObjlst);
   end;
end;

This works with out error.

You state that

At runtime, a form creates a TStringGrid and then the AsmJob which creates those two SAM objects (and load some data from disk in each of them). The AsmJob is also assigned to the grid. When the form is destroyed, the Grid takes care of the AsmJob by freeing it, which frees the TSam objects. Here is the problem: the first object is freed withot problems but the second one dies when its inherited method (in Destroy destructor) is called.

My first question is how does the AsmJob get assigned to TStringGrid so that the TStringGrid destroys the AsmJob, can you show us?

Second, why create a descendant of TObjectList to get it to store two objects and then free free them instead of creating them yourself and letting the TObjectList destroy them as shown above.

The other thing to try is to download the full FastMM4 package from fastmm.sourceforge.net, install it and use the fulldebug dll to trace out exactly what object is failing. You and I are assuming that it's one of the SAM objects and it might or might not be.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!