如果抛出异常,我想有办法向用户报告堆栈跟踪.做这个的最好方式是什么?是否需要大量的额外代码?
回答问题:
如果可能的话,我希望它是便携式的.我想要弹出信息,因此用户可以复制堆栈跟踪并在出现错误时通过电子邮件发送给我.
我的程序运行如下:
exe -p param1 -i param2 -o param3
Run Code Online (Sandbox Code Playgroud)
它崩溃并生成了一个核心转储文件 core.pid
我想通过分析核心转储文件
gdb ./exe -p param1 -i param2 -o param3 core.pid
Run Code Online (Sandbox Code Playgroud)
但是gdb认识到core.pidgdb输入的参数.
在这种情况下如何分析核心转储文件?
有没有办法在每次调用某个函数时在C或C++中正在运行的进程中转储调用堆栈?我的想法是这样的:
void foo()
{
print_stack_trace();
// foo's body
return
}
Run Code Online (Sandbox Code Playgroud)
其中的print_stack_trace工作方式类似于callerPerl.
或类似的东西:
int main (void)
{
// will print out debug info every time foo() is called
register_stack_trace_function(foo);
// etc...
}
Run Code Online (Sandbox Code Playgroud)
在哪里register_stack_trace_function放置某种内部断点,这将导致在调用时打印堆栈跟踪foo.
在某些标准C库中是否存在这样的事情?
我正在使用GCC在Linux上工作.
我有一个测试运行,基于一些不应该影响此行为的命令行开关,行为不同.我的代码有一个伪随机数生成器,我假设它是基于这些开关被不同地调用的.我希望能够使用每组开关运行测试,并查看随机数生成器是否针对每个开关进行不同的调用.
我正在将一个项目转移到新的Android Native Development Kit(即JNI),我想抓住SIGSEGV,如果它发生(可能还有SIGILL,SIGABRT,SIGFPE),以便提供一个很好的崩溃报告对话框,而不是(或之前)当前发生的事情:该过程立即毫不客气地死亡,并且可能是操作系统重启它的一些尝试.(编辑: JVM/Dalvik VM捕获信号并记录堆栈跟踪和其他有用信息;我只是想为用户提供将该信息真正通过电子邮件发送给我的选项.)
情况是:我没有编写的大量C代码完成了这个应用程序中的大部分工作(所有游戏逻辑),虽然它在很多其他平台上都经过了很好的测试,但我完全有可能在我的Android中端口,将它提供垃圾并导致本机代码崩溃,所以我想要当前显示在Android日志中的崩溃转储(本机和Java)(我想在非Android情况下它将是stderr).我可以随意修改C和Java代码,尽管回调(进入和退出JNI)的数量大约为40,显然,小差异的奖励积分.
我听说过J2SE中的信号链接库,libjsig.so,如果我可以在Android上安全地安装这样的信号处理程序,这将解决我的问题的捕捉部分,但我看不到Android/Dalvik这样的库.
java-native-interface android signals segmentation-fault android-ndk
我有一个程序在某处抛出未捕获的异常.我得到的只是一个抛出异常的报告,并没有关于它被抛出的信息.编译为包含调试符号的程序似乎不合逻辑,不通知我在代码中生成异常的位置.
有没有办法告诉我的地方是例外,从短期在gdb设置"抓扔",并呼吁每一个抛出的异常回溯的到来?
这可能是一个非常简单的问题,我正在尝试调试一个生成以下段错误的应用程序 kern.log
kernel: myapp[15514]: segfault at 794ef0 ip 080513b sp 794ef0 error 6 in myapp[8048000+24000]
这是我的问题:
有没有关于segfault上的差异错误号的文档,在这个例子中它是错误6,但我看到错误4,5
这些信息的含义是at bf794ef0 ip 0805130b sp bf794ef0 and myapp[8048000+24000]什么?
到目前为止,我能够使用符号进行编译,当我执行x 0x8048000+24000它时返回一个符号,这是正确的方法吗?到目前为止,我的假设如下:
使用这样的函数:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
void print_trace() {
char pid_buf[30];
sprintf(pid_buf, "--pid=%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
int child_pid = fork();
if (!child_pid) {
dup2(2,1); // redirect output to stderr
fprintf(stdout,"stack trace for %s pid=%s\n",name_buf,pid_buf);
execlp("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);
}
}
Run Code Online (Sandbox Code Playgroud)
我在输出中看到了print_trace的细节.
有什么其他方法可以做到这一点?
我们在专有的assert宏中使用堆栈跟踪来捕获开发人员的错误 - 当捕获错误时,打印堆栈跟踪.
我发现gcc的配对backtrace()/ backtrace_symbols()方法不足:
第一个问题可以通过abi :: __ cxa_demangle来解决.
然而,第二个问题更加艰难.我发现了替换backtrace_symbols().这比gcc的backtrace_symbols()更好,因为它可以检索行号(如果使用-g编译),并且不需要使用-rdynamic进行编译.
Hoverer代码是GNU许可的,所以恕我直言我不能在商业代码中使用它.
任何建议?
PS
gdb能够打印传递给函数的参数.可能已经要求太多了:)
PS 2
类似的问题(感谢nobar)
我一直在使用PRETTY_FUNCTION来输出当前的函数名,但是我已经重新实现了一些函数,并希望找出哪些函数正在调用它们.
在C++中如何获取调用例程的函数名?