所以我有一个崩溃转储,并使用WinDbg,我能够获得堆栈跟踪。但是,它似乎正在跳过其他所有功能。例如,如果实际代码是:
void a()
{
b();
}
void b()
{
c();
}
void c(){}
堆栈跟踪在堆栈框架中有a和c,而不是b。这是预期的行为吗?我能做些什么来查看整个堆栈跟踪?我使用命令“kn”来查看堆栈跟踪。
答案 0 :(得分:1)
编译器可以优化代码。一种优化是内联方法,以便删除call
和ret
语句以及与之相关的所有内容(push
,pop
等。
出于演示目的,我在您的代码中添加了std::cout
语句,我们可以识别这些语句,以便现在完整的代码可以读取
#include "stdafx.h"
#include <iostream>
void c()
{
std::cout << "Hello world";
}
void b()
{
c();
}
void a()
{
b();
}
int _tmain(int argc, _TCHAR* argv[])
{
a();
return 0;
}
在典型的调试版本中,没有优化,您可以看到这些方法。要按照示例,首先启动WinDbg并通过文件/打开可执行文件... 运行可执行文件。
0:000> .symfix e:\debug\symbols
0:000> lm
start end module name
010d0000 010f3000 OptimizedInlined (deferred)
...
0:000> ld OptimizedInlined
Symbols loaded for OptimizedInlined
0:000> x OptimizedInlined!c
010e50c0 OptimizedInlined!c (void)
0:000> bp OptimizedInlined!c
0:000> bl
0 e 010e50c0 0001 (0001) 0:**** OptimizedInlined!c
0:000> g
Breakpoint 0 hit
eax=cccccccc ebx=7efde000 ecx=00000000 edx=00000001 esi=00000000 edi=003ffa00
eip=010e50c0 esp=003ff930 ebp=003ffa00 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
OptimizedInlined!c:
010e50c0 55 push ebp
0:000> u eip L18
OptimizedInlined!c [e:\...\optimizedinlined.cpp @ 8]:
010e50c0 55 push ebp
010e50c1 8bec mov ebp,esp
010e50c3 81ecc0000000 sub esp,0C0h
010e50c9 53 push ebx
010e50ca 56 push esi
010e50cb 57 push edi
010e50cc 8dbd40ffffff lea edi,[ebp-0C0h]
010e50d2 b930000000 mov ecx,30h
010e50d7 b8cccccccc mov eax,0CCCCCCCCh
010e50dc f3ab rep stos dword ptr es:[edi]
010e50de 6854ca0e01 push offset OptimizedInlined!`string' (010eca54)
010e50e3 a1e4000f01 mov eax,dword ptr [OptimizedInlined!_imp_?coutstd (010f00e4)]
010e50e8 50 push eax
010e50e9 e8c9c1ffff call OptimizedInlined!ILT+690(??$?6U?$char_traitsDstdstdYAAAV?$basic_ostreamDU?$char_traitsDstd (010e12b7)
010e50ee 83c408 add esp,8
010e50f1 5f pop edi
010e50f2 5e pop esi
010e50f3 5b pop ebx
010e50f4 81c4c0000000 add esp,0C0h
010e50fa 3bec cmp ebp,esp
010e50fc e838c2ffff call OptimizedInlined!ILT+820(__RTC_CheckEsp) (010e1339)
010e5101 8be5 mov esp,ebp
010e5103 5d pop ebp
010e5104 c3 ret
在发布版本中,了解事情的变化。 WinDbg命令相同,但找不到方法c()
,b()
和a()
。 std::cout
方法调用已内联到wmain()
:
0:000> .symfix e:\debug\symbols
0:000> lm
start end module name
01360000 01367000 OptimizedInlined (deferred)
...
0:000> ld OptimizedInlined
Symbols loaded for OptimizedInlined
0:000> x OptimizedInlined!c
0:000> x OptimizedInlined!b
0:000> x OptimizedInlined!a
0:000> x OptimizedInlined!wmain
013612a0 OptimizedInlined!wmain (int, wchar_t **)
0:000> bp OptimizedInlined!wmain
0:000> bl
0 e 013612a0 0001 (0001) 0:**** OptimizedInlined!wmain
0:000> g
Breakpoint 0 hit
eax=6142f628 ebx=00000000 ecx=0087a6e8 edx=0019def8 esi=00000001 edi=00000000
eip=013612a0 esp=0042f8f8 ebp=0042f934 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
OptimizedInlined!wmain:
013612a0 8b0d44303601 mov ecx,dword ptr [OptimizedInlined!_imp_?coutstd (01363044)] ds:002b:01363044={MSVCP120!std::cout (646c6198)}
0:000> u eip L4
OptimizedInlined!wmain [e:\...\optimizedinlined.cpp @ 23]:
013612a0 8b0d44303601 mov ecx,dword ptr [OptimizedInlined!_imp_?coutstd (01363044)]
013612a6 e895040000 call OptimizedInlined!std::operator<<<std::char_traits<char> > (01361740)
013612ab 33c0 xor eax,eax
013612ad c3 ret
答案 1 :(得分:0)
正如Lieven
已经提到的那样。这是编译器内联函数调用的情况。
我建议有两件事:
一个。如果您可以控制代码和构建环境。构建代码的非优化/调试版本。这将确保编译器不会单独内联函数。
湾在WinDBG中,您可以在View - &gt;下看到反汇编。拆卸。在这里,您可以看到函数b()
的代码实际上位于a()
下。
如果您对组装调试感到满意,您也可以获得本地的价值:)