如何在抛出异常时打印完整的回溯? 我有以下测试程序来提升异常并打印回溯:
#include <iostream>
#include <iostream>
#include <exception>
#include <cstdlib>
#include <execinfo.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void do_backtrace(int signo);
const struct catchSignals_t{
int signo;
const char *name;
} catchSignals[] = {
{ SIGSEGV, "SIGSEGV" },
{ SIGILL, "SIGILL" },
{ SIGFPE, "SIGFPE" },
{ SIGABRT, "SIGABRT" },
{ SIGBUS, "SIGBUS" },
{ SIGUSR2, "SIGUSR2" }
};
bool regHandlers() {
bool result = true;
for (auto i: catchSignals) {
result = result && (signal(i.signo, do_backtrace) != SIG_ERR);
if (!result)
std::cerr << "Failed to install signal:" << i.name;
}
return result;
};
void do_backtrace(int signo) {
std::cerr << "Received signal " << signo << std::endl;
void * array[50];
int size = backtrace(array, 50);
std::cerr << " backtrace returned " << size << " frames\n\n";
char ** messages = backtrace_symbols(array, size);
for (int i = 0; i < size && messages != NULL; ++i) {
std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
}
std::cerr << std::endl;
free(messages);
// abort();
exit(0);
}
void on_terminate() {
std::cout << "on_terminate called" << std::endl;
static bool tried_throw = false;
try {
// try once to re-throw currently active exception
if (!tried_throw++) throw;
}
catch (const std::exception &e) {
std::cerr << __FUNCTION__ << " caught unhandled exception. what(): "
<< e.what() << std::endl;
}
catch (...) {
std::cerr << __FUNCTION__ << " caught unknown/unhandled exception."
<< std::endl;
}
do_backtrace(6);
}
namespace {
static const bool SET_TERMINATE = std::set_terminate(on_terminate);
}
void foo()
{
kill(getpid(), SIGABRT);
abort();
// throw 20;
}
int main() {
regHandlers();
foo();
return 1;
}
在x86主机PC上,它打印完全回溯,我可以转换地址以找出抛出异常的位置,但在目标臂上,这是完全不同的输出。看起来像:
on_terminate backtrace returned 3 frames
[bt]: (0) ./a.out() [0x8a2c]
[bt]: (1) /usr/lib/libstdc++.so.6(+0x4a1e8) [0xb6ecf1e8]
[bt]: (2) /usr/lib/libstdc++.so.6(_ZSt9terminatev+0x1c) [0xb6ecf210]
Aborted (core dumped)
这个问题不仅仅是异常,这可以通过信号处理程序看到 - 回溯也没有完整,我无法找到它上升的位置。
已更新!
构建命令:
arm-buildroot-linux-gnueabi-g++ --std=c++11 -funwind-tables -mapcs-frame -rdynamic main.cc -o test
在代码中使用abort()时,回溯如下:
Received signal 6
backtrace returned 3 frames
[bt]: (0) ./test(_Z12do_backtracei+0x50) [0x8df8]
[bt]: (1) /lib/libc.so.6(__default_sa_restorer_v2+0) [0xb6c90dc0]
[bt]: (2) /lib/libc.so.6(gsignal+0x38) [0xb6c8fb58]
从这个回溯中,无法说出代码崩溃的位置(使用abort()的地方)。
在代码中使用kill(getpid(),SIGABRT) - 后跟跟踪并且看起来没问题:
Received signal 6
backtrace returned 6 frames
[bt]: (0) ./test(_Z12do_backtracei+0x50) [0x8e58]
[bt]: (1) /lib/libc.so.6(__default_sa_restorer_v2+0) [0xb6c61dc0]
[bt]: (2) /lib/libc.so.6(kill+0xc) [0xb6c60e3c]
[bt]: (3) ./test(_Z3foov+0x20) [0x90e4]
[bt]: (4) ./test(main+0x14) [0x90fc]
[bt]: (5) /lib/libc.so.6(__libc_start_main+0x114) [0xb6c4aff4]