我正在Mac OSX Lion上进行一些C ++编程,并希望在崩溃或异常时打印出堆栈跟踪。在下面的讨论中,我尝试了MacPort的gcc47和apple的llvm-gcc42。
我开始使用glog因为它打印了漂亮的堆栈跟踪。如果我通过访问空指针让程序崩溃,那么打印下面的堆栈跟踪看起来很好:
*** Aborted at 1333289352 (unix time) try "date -d @1333289352" if you are using GNU date ***
PC: @ 0x1091a9137 C::h()
*** SIGSEGV (@0x0) received by PID 29623 (TID 0x7fff722d4960) stack trace: ***
@ 0x7fff8cabdcfa _sigtramp
@ 0x1091a9138 C::h()
@ 0x1091a9112 C::g()
@ 0x1091a90ef C::f()
@ 0x1091a903a main
Segmentation fault: 11
但是,如果我通过抛出异常来破坏程序,打印出的堆栈跟踪就不是很有用了:
terminate called after throwing an instance of 'std::runtime_error'
what(): Haha
*** Aborted at 1333289406 (unix time) try "date -d @1333289406" if you are using GNU date ***
PC: @ 0x7fff8450f82a __kill
*** SIGABRT (@0x7fff8450f82a) received by PID 52106 (TID 0x7fff722d4960) stack trace: ***
@ 0x7fff8cabdcfa _sigtramp
Abort trap: 6
我在CentOS系统上尝试过相同的东西,它打印出合理的堆栈跟踪和未捕获的异常,所以它不应该是glog的问题。
所以我的问题是:有没有办法让glog打印出未捕获异常的堆栈跟踪?
答案 0 :(得分:0)
简而言之:尝试安装libunwind并重建google-glog,看看这是否可以解决您的问题。在撰写本文时,这种依赖关系似乎由the OSX SDK给出。
从stacktrace.cc
(稍后移至utilities.h
):
// There are three different ways we can try to get the stack trace:
//
// 1) Our hand-coded stack-unwinder. This depends on a certain stack
// layout, which is used by gcc (and those systems using a
// gcc-compatible ABI) on x86 systems, at least since gcc 2.95.
// It uses the frame pointer to do its work.
//
// 2) The libunwind library. This is still in development, and as a
// separate library adds a new dependency, abut doesn't need a frame
// pointer. It also doesn't call malloc.
//
// 3) The gdb unwinder -- also the one used by the c++ exception code.
// It's obviously well-tested, but has a fatal flaw: it can call
// malloc() from the unwinder. This is a problem because we're
// trying to use the unwinder to instrument malloc().
在后一个文件中:
#if defined(HAVE_LIB_UNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h"
#elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
# elif defined(__x86_64__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86_64-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"
# endif
#endif
#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_H)
# define STACKTRACE_H "stacktrace_generic-inl.h"
#endif
#if defined(STACKTRACE_H)
# define HAVE_STACKTRACE
#endif
使用libunwind进行重建应该允许它优先于堆栈跟踪。如果这不能解决问题,应通知两个工具背后的程序员。
答案 1 :(得分:0)
从OS X 10.6开始,NSException类有一个-callStackSymbols
和一个-callStackReturnAddresses
方法,它可以让您检索抛出异常时的堆栈跟踪。如果要对非异常错误使用相同的机制,请查看Apple文档中的Controlling a Program’s Response to Exceptions。我没有尝试使用C ++异常,但文档声称至少在64位运行时,Objective-C和C ++异常是可互操作的,所以它至少值得一试。