10

我正在尝试追踪访问冲突。可重复性似乎是不确定的,而且很少见,所以我想在进一步讨论之前检查我的一些假设。

在 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,并带有消息“0x01629099 处的访问冲突:读取地址 0x66aed8f8”。

调用堆栈通常是相同的。它是从我调用的虚拟树视图上的绘制事件中调用的,Format('%s %s %s', [vid, node, GetName()])尽管我怀疑这是否真的相关(除了 Format 分配动态内存)。

我正在使用FullDebugMode(显然)和CheckHeapForCorruption选项。

我还建立了以下内容:

  1. 打开CatchUseOfFreedInterfaces并没有显示任何新内容。我仍然遇到相同的访问冲突,并且没有额外的诊断。
  2. 我曾经用 重现了崩溃FullDebugModeScanMemoryPoolBeforeEveryOperation := True,虽然我不记得CatchUseOfFreedInterfaces这次是打开还是关闭。
  3. 这不是线程并发问题;我的应用程序是单线程的。(实际上,这并不完全正确。我正在使用 Virtual TreeView,它创建了一个隐藏的工作线程,但如果这确实是原因,那么错误在 Virtual TreeView,而不是我的代码中,这不太可能。)

我是否正确地认为,尽管CheckHeapForCorruption没有捕获任何东西,但这个异常只能是由于我的代码破坏了堆?还有什么其他可能导致 FastMM4 以这种方式崩溃的吗?

对进一步诊断有什么建议,甚至使崩溃更具重现性?

4

1 回答 1

8

虽然看起来很奇怪,但这是正常行为。如果切换到 CPU 视图,您将看到指令指针位于 FastMM_FullDebugMode.dll 模块内。FastMM 的某些调试功能可以通过设计引发访问冲突。如果您继续执行,您会发现您的应用程序运行正常。

调试会话以这种方式中断可能会非常令人沮丧。我与 FastMM 作者就相关问题进行了一些讨论。似乎 FastMM 调试 DLL 设计为以这种方式工作,结论是没有太多可以做的事情来阻止这些外部异常被引发。

如果有人认识到这种挫败感,并有一个好的解决方案,我将永远感激不尽。

于 2014-03-27T11:07:49.037 回答