c++ - 转储监 Windows 口中 "RtlpAnalyzeHeapFailure"的含义

标签 c++ windows visual-studio crash dump

我正在处理以下访问冲突:

Unhandled exception at 0x77DB2A10 (ntdll.dll) in <Process>.exe.dmp: 
0xC0000005: Access violation reading location 0x184487B8. occurred

源代码如下:

Result CParameter::SetValue(..., ..., <internal_Class>* pBlock, ...)
{
  ...
  <internal_Class>* pStore = nullptr;
  if (!pBlock)
  {
    pStore = &m_Data; // m_Data is a global variable
  }
  else pStore = pBlock;

  if (pStore->pbData)
  {
    pStore->Clear(); // here we have the crash
  }

调用堆栈如下所示:

   ntdll.dll!_RtlpCoalesceFreeBlocks@16()  Unknown Non-user code. Symbols loaded.
   ntdll.dll!@RtlpFreeHeap@16()    Unknown Non-user code. Symbols loaded.
   ntdll.dll!_RtlFreeHeap@12() Unknown Non-user code. Symbols loaded.
   ole32.dll!CRetailMalloc_Free(IMalloc * pThis=0x777476bc, void * pv=0x1842de40) Line 687  C++ Non-user code. Symbols loaded.
   ole32.dll!CoTaskMemFree(void * pv=0x1842de40) Line 475   C++ Non-user code. Symbols loaded.
=> <Process>.exe!CParameter::SetValue(..., <internal_Class> * pBlock=0x00000000, ...) Line 5528 C++ Symbols loaded.

在监 Windows 口中,我看到 &m_Data 的以下值:

0x77e4f9ae {Inside ntdll.dll!_RtlpAnalyzeHeapFailure@12()} {pbData=0xd2b70f3d <Error reading characters of string.> ...}

更多信息:

  • pBlock 的值为 NULL
  • 调试器未知 pStore 的值

问题:

  • 函数“Clear()”在调用堆栈中的什么位置?
  • 监 Windows 口中的值“RtlpAnalyzeHeapFailure”怎么样?这是否意味着我的转储已严重损坏,以至于我无法从中获取任何有用的信息?

提前致谢

最佳答案

Where is the function "Clear()" in the call stack?

这看起来像是内联的。

The value of pStore is unknown by the debugger

这不是还是m_Data吗?

如果你查看崩溃点附近的代码,你可以看到它最近在哪个寄存器中,如果它被保留,那么你应该能够看到它在某个时刻被保存。

该错误是由于内存系统检测到内存被错误释放所致。这可能是因为 m_Data 持有 float 值,或者已经被删除。

我已经制作了类似的功能。

__declspec(noinline) void Type::Clear()
{
    delete pbData;
    pbData = nullptr;
}

__declspec(noinline) void SetValue(Type * pBlock)
{
    Type * pStore = nullptr;
    if (!pBlock)
    {
        pStore = &m_Data; // m_Data is a global variable
    }
    else pStore = pBlock;

    if (pStore->pbData)
    {
        pStore->Clear(); // here we have the crash
    }
}

它的反汇编(来自windbg)是:-

0:000:x86> uf debugging2!SetValue
debugging2!Type::Clear [c:\source\example\debugging2\debugging2.cpp @ 17]:
   17 01041020 56              push    esi
   17 01041021 8bf1            mov     esi,ecx
   18 01041023 6a00            push    0
   18 01041025 ff36            push    dword ptr [esi]
   18 01041027 e85c000000      call    debugging2!operator delete (01041088)
   18 0104102c 83c408          add     esp,8
   19 0104102f c70600000000    mov     dword ptr [esi],0
   19 01041035 5e              pop     esi
   20 01041036 c3              ret

debugging2!SetValue [c:\source\example\debugging2\debugging2.cpp @ 23]:
   23 01041040 833df833040100  cmp     dword ptr [debugging2!m_Data (010433f8)],0
   31 01041047 740a            je      debugging2!SetValue+0x13 (01041053)  
Branch

debugging2!SetValue+0x9 [c:\source\example\debugging2\debugging2.cpp @ 33]:
   33 01041049 b9f8330401      mov     ecx,offset debugging2!m_Data (010433f8)
   33 0104104e e9cdffffff      jmp     debugging2!Type::Clear (01041020)  Branch

debugging2!SetValue+0x13 [c:\source\example\debugging2\debugging2.cpp @ 35]:
   35 01041053 c3              ret  Branch

这表明(在我的例子中)对 Clear() 的调用已被跳转所取代,通过优化将其从堆栈中隐藏起来。 这也表明在地址 01041049 ecx 中加载了调用的值。 MSDN : x86 calling conventions ECX 不是保留值,因此我们无法找到它所保存的值(除了您评论中的 &m_Data 之外)。

但是我们可以查看堆栈上的函数...

在::Clear 函数中,ecx 被移至 esi。因此 esi(被保留)现在具有相同的值。

查看下一个函数(运算符删除),

debugging2!operator delete 
 [f:\dd\vctools\crt\vcstartup\src\heap\delete_scalar_size.cpp @ 14]:
   14 01041088 55              push    ebp
   14 01041089 8bec            mov     ebp,esp
   15 0104108b ff7508          push    dword ptr [ebp+8]
   15 0104108e e890030000      call    debugging2!operator delete (01041423)
   15 01041093 59              pop     ecx
   16 01041094 5d              pop     ebp
   16 01041095 c3              ret

我们看到esi没有改变,也没有保存。所以我们看看堆栈上的下一个函数......

0:000:x86> uf 01041423
Flow analysis was incomplete, some code may be missing
debugging2!operator delete 
[f:\dd\vctools\crt\vcstartup\src\heap\delete_scalar.cpp @ 15]:
   15 01041423 e982090000      jmp     debugging2!free (01041daa)  Branch

在每种情况下,我们都在寻找存储在堆栈上某处的 esi,这样我们就可以找到它......

关于c++ - 转储监 Windows 口中 "RtlpAnalyzeHeapFailure"的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46911731/

相关文章:

C++ 运算符与友元重载

windows - 如何在 Windows 7/8/8.1(尤其是 64 位)上使用未签名的驱动程序

c++ - 如何测量 Windows 平台上应用程序的运行时内存需求?

c# - Visual Studio 在我的 web.configs 中看到错误

visual-studio - NuGet忽略较新版本的依赖项

c++ - 有没有办法知道将来是否会抛出get()?

c++ - 具有缓冲能力的专用线程(每个连接一个线程)(c/c++)

c++ - 如果我们不想将每个元素转换为一个转换元素,而是两个,我们如何使用 std::transform?

c++ - PHP7 - 从源 x86/x64 Windows 编译

visual-studio - Azure WebJob - 创建目录失败