我正在尝试追踪一个访问冲突。可重现性似乎不确定且很少发生,因此在继续之前我想检查一下我的几个假设。
这个访问冲突是在FastMM4版本4.991中的DebugGetMem
函数中引发的,在以下代码中:
if (ASize > (MaximumMediumBlockSize - BlockHeaderSize - FullDebugBlockOverhead))
or CheckFreeBlockUnmodified(Result, GetAvailableSpaceInBlock(Result) + BlockHeaderSize, boGetMem) then
begin
{Set the allocation call stack}
GetStackTrace(@PFullDebugBlockHeader(Result).AllocationStackTrace, StackTraceDepth, 1);
{Set the thread ID of the thread that allocated the block}
PFullDebugBlockHeader(Result).AllocatedByThread := GetThreadID; // ** AV Here
{Block is now in use: It was allocated by this routine}
PFullDebugBlockHeader(Result).AllocatedByRoutine := @DebugGetMem;
异常情况是:
Project Workstation.exe引发异常类$C0000005,消息为“访问地址0x66aed8f8时读取地址0x01629099”。
调用堆栈通常相同。它是从虚拟树视图的绘制事件中被调用的,在其中我调用了Format('%s %s %s', [vid, node, GetName()])
,尽管我怀疑这并不重要(除了Format分配动态内存之外)。
我正在使用FullDebugMode
(显然)和CheckHeapForCorruption
选项。
我还确定了以下内容:
- 启用
CatchUseOfFreedInterfaces
没有显示任何新信息。我仍然得到相同的访问冲突,没有额外的诊断信息。 - 我曾经使用
FullDebugModeScanMemoryPoolBeforeEveryOperation := True
复制了崩溃,尽管我无法记得此时是否开启了CatchUseOfFreedInterfaces
。 - 这不是线程并发问题;我的应用程序是单线程的。(实际上,这并不完全正确。我正在使用虚拟树形视图,它创建了一个隐藏的工作线程,但如果这真的是原因,那么错误就在虚拟树形视图中,而不是我的代码,这是相当不可能的。)
我是否正确地认为,尽管CheckHeapForCorruption
没有捕获到任何东西,此异常只能是由于我的代码损坏了堆栈?还有其他导致FastMM4以这种方式崩溃的原因吗?
有关进一步诊断的建议,甚至使崩溃更易于复制的建议吗?