gpt4 book ai didi

c++ - 如何使用带有行号信息的 gcc 获取 C++ 的堆栈跟踪?

转载 作者:IT老高 更新时间:2023-10-28 12:32:27 27 4
gpt4 key购买 nike

我们在专有的 assert 中使用堆栈跟踪来捕捉开发人员的错误 - 当发现错误时,会打印堆栈跟踪。

我发现 gcc 的对 backtrace()/backtrace_symbols() 方法不足:

  1. 名字被打乱了
  2. 无线路信息

第一个问题可以通过 abi::__cxa_demangle 解决.

但是第二个问题更难。我找到了 replacement for backtrace_symbols() .这比 gcc 的 backtrace_symbols() 更好,因为它可以检索行号(如果使用 -g 编译)并且您不需要使用 -rdynamic 编译。

悬停代码是 GNU 许可的,所以恕我直言,我不能在商业代码中使用它。

有什么建议吗?

附言

gdb 能够打印出传递给函数的参数。 可能要求已经太多了:)

PS 2

Similar question (感谢诺巴)

最佳答案

因此,您需要一个打印堆栈跟踪的独立函数,该函数具有 gdb 堆栈跟踪所具有的所有功能,并且不会终止您的应用程序。答案是以非交互模式自动启动 gdb 以执行您想要的任务。

这是通过在子进程中执行 gdb、使用 fork() 并编写脚本以在应用程序等待它完成时显示堆栈跟踪来完成的。这可以在不使用核心转储且不中止应用程序的情况下执行。我通过查看这个问题学会了如何做到这一点:How it's better to invoke gdb from program to print it's stacktrace?

与该问题一起发布的示例对我来说并没有完全按照所写的那样工作,所以这是我的“固定”版本(我在 Ubuntu 9.04 上运行)。

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/prctl.h>

void print_trace() {
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
int child_pid = fork();
if (!child_pid) {
dup2(2,1); // redirect output to stderr - edit: unnecessary?
execl("/usr/bin/gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
abort(); /* If gdb failed to start */
} else {
waitpid(child_pid,NULL,0);
}
}

如引用的问题所示,gdb 提供了您可以使用的其他选项。例如,使用“bt full”而不是“bt”会生成更详细的报告(局部变量包含在输出中)。 gdb 的联机帮助页比较简单,但可以使用完整的文档 here .

由于这是基于 gdb,因此输出包括 解构名称行号函数参数,甚至还有可选的 局部变量。此外,gdb 是线程感知的,因此您应该能够提取一些特定于线程的元数据。

这是我使用此方法看到的堆栈跟踪类型的示例。

0x00007f97e1fc2925 in waitpid () from /lib/libc.so.6
[Current thread is 0 (process 15573)]
#0 0x00007f97e1fc2925 in waitpid () from /lib/libc.so.6
#1 0x0000000000400bd5 in print_trace () at ./demo3b.cpp:496
2 0x0000000000400c09 in recursive (i=2) at ./demo3b.cpp:636
3 0x0000000000400c1a in recursive (i=1) at ./demo3b.cpp:646
4 0x0000000000400c1a in recursive (i=0) at ./demo3b.cpp:646
5 0x0000000000400c46 in main (argc=1, argv=0x7fffe3b2b5b8) at ./demo3b.cpp:70

注意:我发现这与 valgrind 的使用不兼容(可能是由于 Valgrind 使用了虚拟机)。当您在 gdb session 中运行程序时,它也不起作用(无法将“ptrace”的第二个实例应用于进程)。

关于c++ - 如何使用带有行号信息的 gcc 获取 C++ 的堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4636456/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com