【发布时间】:2011-06-26 22:56:28
【问题描述】:
我一直在努力在 Windows 可执行文件中获取调用堆栈。我尝试了几种不同的方法来获取调用堆栈。以下是一些示例。请注意,我稍微修改了它们并删除了错误处理以使它们易于理解,因此它们可能无法按原样编译。我想你明白了。
简单的方法:
const int max_entries = 10;
void *entries[max_entries];
return CaptureStackBackTrace(0, max_entries, entries, 0);
低级方式:
const int max_entries = 10;
void *entries[max_entries];
void **frame = 0;
__asm { mov frame, ebp }
unsigned int i = 0;
while(frame && i < max_entries) {
entries[i++] = frame[1];
frame = (void **)frame[0];
}
兼容方式:
void *entries[max_entries];
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 stack_frame;
ZeroMemory(&stack_frame, sizeof(STACKFRAME64));
stack_frame.AddrPC.Offset = context.Eip;
stack_frame.AddrPC.Mode = AddrModeFlat;
stack_frame.AddrFrame.Offset = context.Ebp;
stack_frame.AddrFrame.Mode = AddrModeFlat;
stack_frame.AddrStack.Offset = context.Esp;
stack_frame.AddrStack.Mode = AddrModeFlat;
unsigned int num_frames = 0;
while (true) {
if (!StackWalk64(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(),
GetCurrentThread(), &stack_frame, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL))
break;
if (stack_frame.AddrPC.Offset == 0)
break;
entries[num_frames++] = reinterpret_cast<void *>(stack_frame.AddrPC.Offset);
}
我的问题是它们在未优化的构建中工作,但没有完全优化。发生的事情是我得到一个损坏的条目,然后他们退出了循环。在调试中,我得到了完整的调用堆栈,当我稍后查找符号时,一切都是正确的。
我不明白当调试器一直在执行此操作时,要在所有构建中进行这项工作是多么困难。我可以明确地说,在代码生成中没有省略帧指针。我先构建调试,然后只将优化从无更改为完全优化并重建以重现调用堆栈故障。
任何解决方案的提示将不胜感激。
/乔纳斯
【问题讨论】:
-
您没有在打开帧指针优化的情况下进行编译,是吗?
-
在代码生成中不会省略帧指针,如果这就是你的意思的话。