我正在处理以下访问冲突:
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
的值
问题:
提前致谢
答案 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存储在堆栈的某个位置,以便我们找到它...