【问题标题】:How do I obtain a stack trace on Windows without using dbghelp.dll?如何在不使用 dbghelp.dll 的情况下在 Windows 上获取堆栈跟踪?
【发布时间】:2010-09-28 09:14:36
【问题描述】:

如何在不使用 dbghelp.dll 的情况下在 Windows 上获取地址的堆栈跟踪?

我不需要知道与地址相关的符号或函数名称,我只需要地址列表——类似于 backtrace of *nix systems

谢谢!

【问题讨论】:

标签: c++ c stack stack-trace dbghelp


【解决方案1】:

查看位于 Kernel32.dll 中的 CaptureStackBackTrace() 函数。这应该可以满足您的所有需求。

通过向上遍历堆栈并记录每一帧的信息来捕获堆栈回溯。

USHORT WINAPI CaptureStackBackTrace(
  __in       ULONG FramesToSkip,
  __in       ULONG FramesToCapture,
  __out      PVOID *BackTrace,
  __out_opt  PULONG BackTraceHash
);

【讨论】:

  • 看起来不错。但是我使用的是 VS 2005,并且在 winbase.h 中没有定义 CaptureStackBackTrace no RtlCaptureBackTrace。我将尝试手动包含 RtlCaptureBackTrace(...) 的函数原型,看看这是否对我有用。谢谢!
  • 太酷了!我至少编写了 3 次堆栈跟踪代码,但不知道这存在。谢谢!
  • @Uhall:您可以尝试安装更新的 Windows SDK。尽管 MSDN 页面确实列出了从 Windows Vista 开始的 Windows SDK 中包含的最低支持客户端。
【解决方案2】:

如果您想非常以不可移植的方式执行此操作,您可以只读取 EBP 寄存器并自己遍历堆栈。这仅适用于 x86 架构,并且它还假定您使用的 C 运行时在调用第一个函数之前将 EBP 正确初始化为 0。

uint32_t read_ebp(void)
{
    uint32_t my_ebp;
    __asm
    {
        mov ebp, my_ebp
    }

    return my_ebp;
}

void backtrace(void)
{
    uint32_t ebp = read_ebp();

    printf("backtrace:\n");

    while(ebp != 0)
    {
        printf("0x%08x\n", ebp);
        ebp = ((uint32_t *)ebp)[1];
    }
}

【讨论】:

  • 对于发布版本,这只会给你前几帧。为此,您需要设置“Omit Frame Pointers”=No。
  • destination 是第一位的,所以你需要 mov my_ebp, ebp.. 除此之外它很酷
【解决方案3】:

以前的变体对我不起作用(msvc 6),所以:

unsigned long prev;
unsigned long addr;
__asm { mov prev, ebp }
while(addr!=0) { 
  addr = ((unsigned long *)prev)[1]; 
  printf("0x%08x\n", addr); 
  prev = ((unsigned long *)prev)[0]; 
}
亚当,谢谢你强调的方式!

【讨论】:

    猜你喜欢
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    • 2016-05-12
    • 2017-10-31
    相关资源
    最近更新 更多