转储监视窗口中“RtlpAnalyzeHeapFailure”的含义

时间:2017-10-24 13:22:40

标签: 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.

在观察窗口内,我看到&amp; m_Data的以下值:

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

更多信息:

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

问题:

  • 调用堆栈中的函数“Clear()”在哪里?
  • 观察窗口的价值“RtlpAnalyzeHeapFailure”怎么样?这是否意味着我的转储损坏了很多,我无法从中获取任何有用的信息?

提前致谢

1 个答案:

答案 0 :(得分:0)

  

功能在哪里&#34;清除()&#34;在调用堆栈中?

这看起来像是内联的。

  

调试器

未知pStore的值

它还没有来自m_Data吗?

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

错误是由于内存系统检测到内存被错误地释放。这可能是m_Data持有浮动值,或者已被删除。

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

__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不是保留值,因此我们无法找到它所持有的值(除了它似乎是你评论中的&amp; m_Data)。

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

在:: Clear功能中,ecx被移动到esi。因此,esi(保留)现在具有相同的值。

查看下一个函数(operator delete),

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:86&GT; uf 01041423 流量分析不完整,可能缺少某些代码     debugging2!operator delete     [f:\ dd \ vctools \ crt \ vcstartup \ src \ heap \ delete_scalar.cpp @ 15]:        15 01041423 e982090000 jmp debugging2!free(01041daa)Branch

在每种情况下,我们都希望将esi存储在堆栈的某个位置,以便我们找到它...