我正在试图追踪访问违规。可重复性似乎是不确定的,而且很少,所以在我进一步讨论之前,我想检查一下我的一些假设。
在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 station.exe引发异常类$C0000005,提示"访问违规在0x01629099:读取地址0x66aed8f8"。
调用堆栈通常相同。它被从虚拟树视图上的一个绘制事件调用,我在其中调用Format('%s %s %s', [vid, node, GetName()])
,尽管我怀疑这是真正相关的(除了格式分配动态内存)。
我使用FullDebugMode
(显然)和CheckHeapForCorruption
选项。
我还建立了以下内容:
- 打开
CatchUseOfFreedInterfaces
没有显示任何新内容。我仍然得到相同的访问冲突,没有额外的诊断。 - 我曾经用
FullDebugModeScanMemoryPoolBeforeEveryOperation := True
重现了崩溃,虽然我不记得CatchUseOfFreedInterfaces
在这种情况下是开还是关。 这不是线程并发问题;我的应用程序是单线程的。(事实上,这并不完全正确。我正在使用Virtual TreeView,它创建了一个隐藏的工作线程,但如果这真的是原因,那么错误是在Virtual TreeView,而不是我的代码,这是相当不可能的。
我认为正确吗,尽管CheckHeapForCorruption
没有捕获任何东西,这个异常只能是由于我的代码损坏堆?还有其他什么原因会导致FastMM4以这种方式崩溃吗?
有什么建议可以进一步诊断,甚至使崩溃更容易重现吗?
虽然看起来很奇怪,但这是正常的行为。如果您切换到CPU视图,您将看到指令指针位于FastMM_FullDebugMode.dll模块内。FastMM的一些调试功能在设计上可能会引发访问冲突。如果你继续执行,你会发现你的应用程序运行正确。
以这种方式中断调试会话是非常令人沮丧的。我与FastMM的作者就一个相关问题进行了一些讨论。似乎FastMM调试DLL被设计成以这种方式工作,结论是没有很多可以做的事情来阻止这些外部异常被提出。
如果有人认识到这种挫折,并有一个好的解决方案,我将永远感激。