Debugging 页面堆不';记录有用的堆栈信息?

Debugging 页面堆不';记录有用的堆栈信息?,debugging,visual-c++,windbg,gflags,pageheap,Debugging,Visual C++,Windbg,Gflags,Pageheap,我正在尝试使用正常页面堆(未满)测试崩溃场景(在一个独立的测试应用程序中) 我已经把国旗挂好了 gflags /p /enable Test.exe 我用一个元素覆盖一个整数缓冲区 ... const size_t s = 100; vector<int> v1(s, 0); int* v1_base = &v1[0]; write_to_memory_int(v1_base, s+1); ... 也就是说,有一个分配堆栈跟踪,但它在RtlAllocateHeap处停止,

我正在尝试使用正常页面堆(未满)测试崩溃场景(在一个独立的测试应用程序中)

我已经把国旗挂好了

gflags /p /enable Test.exe
我用一个元素覆盖一个整数缓冲区

...
const size_t s = 100;
vector<int> v1(s, 0);
int* v1_base = &v1[0];
write_to_memory_int(v1_base, s+1);
...
也就是说,有一个分配堆栈跟踪,但它在
RtlAllocateHeap
处停止,这显然是完全无用的

查看内存中的堆栈跟踪:

dt _DPH_BLOCK_INFORMATION ....-0x20

=>

0:005> dds 0x03e556f4
03e556f4  00000000
03e556f8  00002050
03e556fc  00050000
03e55700  1122a6a7 verifier!AVrfpDphNormalHeapAllocate+0xd7
03e55704  11228f6e verifier!AVrfDebugPageHeapAllocate+0x30e
03e55708  77950d96 ntdll!RtlDebugAllocateHeap+0x30
03e5570c  7790af0d ntdll!RtlpAllocateHeap+0xc4
03e55710  778b3cfe ntdll!RtlAllocateHeap+0x23a
03e55714  00000000
03e55718  00003001
03e5571c  0004005e
事实上,似乎没有更多的记录

如何修复页面堆以记录有用的堆栈跟踪

请注意,测试项目不是用FPO(/Oy)编译的,我不希望
RtlAllocateHeap
受到FPO的影响


更新:我通过手动进入分配(见下文)检查了相关调用的FPO性,VC80(VS2005)运行库的
malloc
op new
似乎都启用了某种形式的FPO。。。所以这可能会弄乱页面堆的堆栈DB的堆栈跟踪

0:004> kv
ChildEBP RetAddr  Args to Child              
077efa7c 77c8af0d 05290000 01001002 00000190 ntdll!RtlDebugAllocateHeap+0x16 (FPO: [Non-Fpo])
077efb60 77c33cfe 00000190 00000000 00000000 ntdll!RtlpAllocateHeap+0xc4 (FPO: [Non-Fpo])
077efbe4 72344d83 05290000 01001002 00000190 ntdll!RtlAllocateHeap+0x23a (FPO: [Non-Fpo])
077efc04 62f595ee 00000190 00000000 00000000 MSVCR80!malloc+0x7a (FPO: [1,0,0]) (CONV: cdecl) 
077efc1c 00406a44 00000190 ebecf74f 00000001 MFC80U!operator new+0x2f (FPO: [Uses EBP] [1,0,0]) (CONV: cdecl)
077efc48 00405479 00000064 00000000 3fffffff Test!std::_Allocate<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > > >+0x84 (FPO: [Non-Fpo]) (CONV: cdecl)
077efcb8 004049f4 00000064 ebecf68f 00000000 Test!std::vector<unsigned int,std::allocator<unsigned int> >::_Buy+0x69 (FPO: [Non-Fpo]) (CONV: thiscall)
077efd88 00402a4f 00000064 077efdc0 ebecf44b Test!std::vector<int,std::allocator<int> >::_Construct_n+0x44 (FPO: [Non-Fpo]) (CONV: thiscall)
077eff4c 72342848 00000000 ebec8474 00000000 Test!crashFN+0x35f (FPO: [Non-Fpo]) (CONV: cdecl) 
077eff84 723428c8 75da33aa 072ab3d8 077effd4 MSVCR80!_callthreadstart+0x1b (FPO: [Non-Fpo]) (CONV: cdecl)
077eff88 75da33aa 072ab3d8 077effd4 77c39f72 MSVCR80!_threadstart+0x5a (FPO: [1,0,0]) (CONV: stdcall)
077eff94 77c39f72 072ab3d8 70fca8b2 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
077effd4 77c39f45 7234286e 072ab3d8 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo])
077effec 00000000 7234286e 072ab3d8 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])
0:004>kv
ChildEBP将参数重新寻址到Child
077efa7c 77c8af0d 05290000 01002 00000190 ntdll!RtlDebugAllocateHeap+0x16(FPO:[非FPO])
077efb60 77c33cfe 00000190 00000000 00000000 ntdll!RtlpAllocateHeap+0xc4(FPO:[非FPO])
077efbe4 72344d83 05290000 01001002 00000190 ntdll!RTLALLOCATHEAP+0x23a(FPO:[非FPO])
077efc04 62f595ee 00000190 00000000 00000000 MSVCR80!malloc+0x7a(FPO:[1,0,0])(CONV:cdecl)
077efc1c 00406a44 00000190 ebecf74f 0000000 1 MFC80U!运算符new+0x2f(FPO:[使用EBP][1,0,0])(CONV:cdecl)
077efc48 00405479 000000 64 00000000 3fffffff测试!std::_Allocate+0x84(FPO:[非FPO])(CONV:cdecl)
077efcb8 004049f4 00000064 ebecf68f 00000000测试!std::vector::_Buy+0x69(FPO:[非FPO])(CONV:thiscall)
077efd88 00402A4 F 00000064 077efdc0 ebecf44b测试!std::vector::_Construct_n+0x44(FPO:[非FPO])(CONV:thiscall)
077eff4c 72342848 00000000 ebec8474 00000000测试!crashFN+0x35f(FPO:[非FPO])(CONV:cdecl)
077eff84 723428c8 75da33aa 072ab3d8 077effd4 MSVCR80_callthreadstart+0x1b(FPO:[非FPO])(CONV:cdecl)
077eff88 75da33aa 072ab3d8 077effd4 77c39f72 MSVCR80_threadstart+0x5a(FPO:[1,0,0])(CONV:stdcall)
077eff94 77c39f72 072ab3d8 70fca8b2 00000000内核32!BaseThreadInitThunk+0xe(FPO:[非FPO])
077effd4 77c39f45 7234286e 072ab3d8 00000000 ntdll__RtlUserThreadStart+0x70(FPO:[非FPO])
077effec 00000000 7234286e 072ab3d8 00000000 ntdll_RtlUserThreadStart+0x1b(FPO:[非FPO])


感谢@Marc Sherman在评论中指出我应该查看真实的分配堆栈跟踪

正如已经编辑到问题中的,VC80(VS2005)是这里的问题,因为它的CRT已启用FPO,如堆栈跟踪中所示:

MSVCR80!malloc+0x7a (FPO: [1,0,0]) (CONV: cdecl) 
MFC80U!operator new+0x2f (FPO: [Uses EBP] [1,0,0]) (CONV: cdecl)
现在,有一个锚来搜索,我们发现以下内容:

添加一些引号:

特别是,默认的malloc实现 Visual C++ 2005上的静态链接CRT不使用帧 指针,但它将ebp作为暂存器转储

这一切意味着什么?嗯,任何使用malloc构建的 VisualC++ 2005将无法用UMDH或其他任何东西诊断 依赖于基于ebp的堆栈跟踪,至少不依赖于x86版本。

评论中还有一条回复,内容很好:

马克·罗伯茨说:2008年2月25日下午3:03

你好,

为8.0 CRT启用FPO不是故意的。Visual Studio 2008 CRT(9.0)未启用FPO,UMDH应能正常工作 通常

对于8.0,UMDH的替代方案是使用LeakDiag。漏诊 实际上,它将使用内存分配器来获取堆栈跟踪。 这使得它比UMDH更通用,因为它可以钩住几个 不同粒度的不同分配器类型(从 c运行时到原始虚拟内存分配)

默认情况下,LeakDiag只是遍历堆栈基指针,但它可以 修改为使用Dbghlp StackWalkAPI解析FPO数据。这 将产生完整的堆栈,尽管性能损失更高。在…上 另一方面,您可以将堆栈遍历行为自定义为仅执行 达到一定深度等,以将性能惩罚降至最低

请在此处找到LeakDiag:


也许C++运行时和/或CRT是编译FPO的。如果您使用
dds 0x03e556f4 L80
增加dds的范围会怎样?你看到任何有趣的返回地址了吗?@Marc:没有,除了第一个stac(只是更多的、不相关的堆栈)之外,似乎没有任何有趣的东西。关于你在内存中发布的堆栈跟踪,奇怪的是,这些返回地址会立即相互跟随。通常,您会在它们之间看到一个已保存的EBP。您首先是如何找到值0x03e556f4的?@Marc-这是页面堆堆栈数据库记录的堆栈跟踪要排除FPO,如果在
ntdll上设置断点会怎么样!RtlpAllocateHeap
和显示FPO数据(如果有的话)的问题
kv
。多年来,MSVC库中的FPO一直是一个反复出现的问题,可以选择绕过的是运行调试版本,而调试版本通常没有FPO(但不确定您的版本)。
0:004> kv
ChildEBP RetAddr  Args to Child              
077efa7c 77c8af0d 05290000 01001002 00000190 ntdll!RtlDebugAllocateHeap+0x16 (FPO: [Non-Fpo])
077efb60 77c33cfe 00000190 00000000 00000000 ntdll!RtlpAllocateHeap+0xc4 (FPO: [Non-Fpo])
077efbe4 72344d83 05290000 01001002 00000190 ntdll!RtlAllocateHeap+0x23a (FPO: [Non-Fpo])
077efc04 62f595ee 00000190 00000000 00000000 MSVCR80!malloc+0x7a (FPO: [1,0,0]) (CONV: cdecl) 
077efc1c 00406a44 00000190 ebecf74f 00000001 MFC80U!operator new+0x2f (FPO: [Uses EBP] [1,0,0]) (CONV: cdecl)
077efc48 00405479 00000064 00000000 3fffffff Test!std::_Allocate<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > > >+0x84 (FPO: [Non-Fpo]) (CONV: cdecl)
077efcb8 004049f4 00000064 ebecf68f 00000000 Test!std::vector<unsigned int,std::allocator<unsigned int> >::_Buy+0x69 (FPO: [Non-Fpo]) (CONV: thiscall)
077efd88 00402a4f 00000064 077efdc0 ebecf44b Test!std::vector<int,std::allocator<int> >::_Construct_n+0x44 (FPO: [Non-Fpo]) (CONV: thiscall)
077eff4c 72342848 00000000 ebec8474 00000000 Test!crashFN+0x35f (FPO: [Non-Fpo]) (CONV: cdecl) 
077eff84 723428c8 75da33aa 072ab3d8 077effd4 MSVCR80!_callthreadstart+0x1b (FPO: [Non-Fpo]) (CONV: cdecl)
077eff88 75da33aa 072ab3d8 077effd4 77c39f72 MSVCR80!_threadstart+0x5a (FPO: [1,0,0]) (CONV: stdcall)
077eff94 77c39f72 072ab3d8 70fca8b2 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
077effd4 77c39f45 7234286e 072ab3d8 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo])
077effec 00000000 7234286e 072ab3d8 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])
MSVCR80!malloc+0x7a (FPO: [1,0,0]) (CONV: cdecl) 
MFC80U!operator new+0x2f (FPO: [Uses EBP] [1,0,0]) (CONV: cdecl)