在Mac OSX上未捕获异常时回溯

时间:2012-04-01 13:44:24

标签: c++ macos

我正在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打印出未捕获异常的堆栈跟踪?

2 个答案:

答案 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 ++异常是可互操作的,所以它至少值得一试。