解释应用程序验证程序输出:堆损坏或将堆栈地址误解为堆地址?
我们有一个测试用例,它会导致基于 MFC 的大型应用程序因堆损坏错误而崩溃。
我使用 App Verifier 打开了相关 DLL 的页面堆(不幸的是,由于其他原因,为整个进程打开堆是行不通的。)验证器没有给我们提供比我们已经拥有的更多的信息;它与最初的崩溃在同一点触发。
现在我有两种相互竞争的理论。您认为哪种理论更有可能是正确的?您的下一步计划是什么?
- 这确实是堆损坏。验证程序无法捕获原始损坏,因为它发生在另一个 DLL 中。我们应该尝试激活更多 DLL 的验证程序并确定哪些代码正在损坏堆。
- 堆没问题;问题是我们将堆栈地址视为堆地址。我们应该进一步研究这个调用堆栈中的代码以找出问题所在。
我倾向于#2,因为 free() 的参数看起来像一个堆栈地址,但到目前为止,没有人提出解释这是如何实现的。
这是调用堆栈的片段。 MyString 是 CString 的简单包装。 MyAppDll 是设置为使用页堆的 DLL。
msvcr90.dll!free(void * pBlock=0x000000000012d6e8) Line 110 mfc90u.dll!ATL::CStringT > >::~CStringT > >() Line 1011 + 0x1e bytes MyStringDll.dll!MyString::~MyString() Line 59 MyAppDll.dll!doStuffWithLotsOfStringInlining(MyClass* input=0x000000000012d6d0) Line 863 + 0x26 bytes
以下是 free() 堆栈帧内的寄存器:
RAX = 0000000000000000 RBX = 000000000012D6E8 RCX = 0000000000000000 RDX = 0000000000000000 RSI = 000000000012D6D0 RDI = 00000000253C1090 R8 = 0000000000000000 R9 = 0000000000000000 R10 = 0000000000000000 R11 = 0000000000000000 R12 = 000000000012D7D0 R13 = 000007FFFFC04CE0 R14 = 0000000025196600 R15 = 0000000000000000 RIP = 00000000725BC7BC RSP = 000000000012D570 RBP = 000007FFF3670900 EFL = 00000000
这是应用程序验证程序消息:
VERIFIER STOP 0000000000000010: pid 0x1778: Corrupted start stamp for heap block. 00000000083B1000 : Heap handle used in the call. 000000006DD394E8 : Heap block involved in the operation. 54D32858A8747589 : Size of the heap block. 000000005E33BA8D : Corrupted stamp value.
We have a test case that crashes our big MFC-based app with a heap corruption error.
I turned on the page heap using App Verifier for the DLL in question (turning the heap on for the entire process isn't workable for other reasons, unfortunately.) The verifier didn't give us any more information than we already had; it triggered at the same point as the original crash.
Right now I have two competing theories. Which theory do you think is more likely to be correct, and what would your next steps be?
- This is indeed heap corruption. The verifier isn't catching the original damage because it's happening in another DLL. We should try to activate the verifier for more DLLs and determine what code is damaging the heap.
- The heap is fine; the problem is that we are treating a stack address as a heap address. We should study the code in this callstack further to figure out what's going wrong.
I'm leaning #2 because the parameter to free() looks like a stack address, but so far nobody has proposed an explanation for how this is possible.
Here's a snippet of the call stack. MyString is a simple wrapper around CString. MyAppDll is the DLL that's set to use the page heap.
msvcr90.dll!free(void * pBlock=0x000000000012d6e8) Line 110 mfc90u.dll!ATL::CStringT > >::~CStringT > >() Line 1011 + 0x1e bytes MyStringDll.dll!MyString::~MyString() Line 59 MyAppDll.dll!doStuffWithLotsOfStringInlining(MyClass* input=0x000000000012d6d0) Line 863 + 0x26 bytes
Here are the registers inside the free() stack frame:
RAX = 0000000000000000 RBX = 000000000012D6E8 RCX = 0000000000000000 RDX = 0000000000000000 RSI = 000000000012D6D0 RDI = 00000000253C1090 R8 = 0000000000000000 R9 = 0000000000000000 R10 = 0000000000000000 R11 = 0000000000000000 R12 = 000000000012D7D0 R13 = 000007FFFFC04CE0 R14 = 0000000025196600 R15 = 0000000000000000 RIP = 00000000725BC7BC RSP = 000000000012D570 RBP = 000007FFF3670900 EFL = 00000000
And here's the app verifier message:
VERIFIER STOP 0000000000000010: pid 0x1778: Corrupted start stamp for heap block. 00000000083B1000 : Heap handle used in the call. 000000006DD394E8 : Heap block involved in the operation. 54D32858A8747589 : Size of the heap block. 000000005E33BA8D : Corrupted stamp value.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您的字符串或它的用户正在某处溢出/下溢字符串的缓冲区,可能是针对字符串指针旁边的字段,然后您尝试释放该字段。
您的 RSP 是 12D570,与您尝试释放的内容相距 94 个四边形(整数),因此在这之间的某个位置,缓冲区发生了一些不良情况。
验证您没有执行任何不安全的字符串操作,并且您正在正确阅读有关将缓冲区/字符串传递到您正在使用的 DLL 中的文档。
如果您想要更准确的答案,您的问题可能需要更多代码。
I think your string or users of it is/are overflowing/underflowing the string's buffer somewhere, probably against a field which is next to the string pointer, which you then try to free.
Your RSP is 12D570, which is 94 quads (ints) away from what you are trying to free, so somewhere between there, something bad is happening with buffers.
Verify that you are not doing any unsafe string ops and that you are correctly reading the documentation for passing buffers/strings into the DLLs you are using.
You probably need more code in your question if you want a more exact answer.