来自未处理异常的c ++堆栈跟踪? [英] c++ stack trace from unhandled exception?

查看:201
本文介绍了来自未处理异常的c ++堆栈跟踪?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题之前已经被问过,并且已经有Windows特定的答案,但没有令人满意的gcc答案。我可以使用 set_terminate()设置一个将被调用的函数(代替 terminate())未处理的异常被抛出。我知道如何使用backtrace库从程序中的给定点生成堆栈跟踪。但是,当我的终止替换被调用时,这不会有帮助,因为在这一点堆栈已经被解开了。



然而,如果我只是允许程序 abort(),它将产生一个核心转储,其中包含从抛出异常点的完整堆栈信息。所以信息在那里 - 但是有没有一个程序化的方式来获取它,例如可以记录,而不是检查核心文件?

解决方案

编辑答案:



您可以使用 std :: set_terminate

  #include< cstdlib> 
#include< iostream>
#include< stdexcept>

#include< execinfo.h>

void
handler()
{
void * trace_elems [20];
int trace_elem_count(backtrace(trace_elems,20));
char ** stack_syms(backtrace_symbols(trace_elems,trace_elem_count)); (int i = 0; i< trace_elem_count; ++ i)

{
std :: cout<< stack_syms [i]<< \\\
;
}
free(stack_syms);

exit(1);
}

int foo()
{
throw std :: runtime_error(hello);
}

void bar()
{
foo();
}

void baz()
{
bar();
}

int
main()
{
std :: set_terminate(handler);
baz();
}

给出此输出:

  samm @ macmini〜> ./a.out 
./a.out [0x10000d20]
/usr/lib/libstdc++.so.6 [0xf9bb8c8]
/usr/lib/libstdc++.so.6 [0xf9bb90c ]
/usr/lib/libstdc++.so.6 [0xf9bbaa0]
./a.out [0x10000c18]
./a.out [0x10000c70]
./a。 out [0x10000ca0]
./a.out [0x10000cdc]
/lib/libc.so.6 [0xfe4dd80]
/lib/libc.so.6 [0xfe4dfc0]
samjmill @ bgqfen4〜>假设你的二进制文件中有调试符号,那么你可以使用addr2line来构建一个漂亮的堆栈跟踪postmort

  samm @ macmini〜> addr2line 0x10000c18 
/home/samm/foo.cc:23
samm @ macmini〜>

原始答案在






我以前使用 boost :: error_info 使用 backtrace execinfo.h 注入堆栈跟踪被抛出的异常。

  typedef boost :: error_info< struct tag_stack_str,std :: string> stack_info; 

然后当捕捉异常时,可以执行

 } catch(const std :: exception& e){
if(std :: string const * stack boost :: get_error_info< stack_error_info>(e)){
std :: cout<<<堆栈<的std :: ENDL;
}
}


This question has been asked before and there have been windows-specific answers but no satisfactory gcc answer. I can use set_terminate() to set a function that will be called (in place of terminate()) when an unhandled exception is thrown. I know how to use the backtrace library to generate a stack trace from a given point in the program. However, this won't help when my terminate-replacement is called since at that point the stack has been unwound.

Yet if I simply allow the program to abort(), it will produce a core-dump which contains the full stack information from the point at which the exception was thrown. So the information is there -- but is there a programmatic way to get it, for example so it can be logged, rather than having to examine a core file?

解决方案

Edited Answer:

You can use std::set_terminate

#include <cstdlib>
#include <iostream>
#include <stdexcept>

#include <execinfo.h>

void
handler()
{
    void *trace_elems[20];
    int trace_elem_count(backtrace( trace_elems, 20 ));
    char **stack_syms(backtrace_symbols( trace_elems, trace_elem_count ));
    for ( int i = 0 ; i < trace_elem_count ; ++i )
    {
        std::cout << stack_syms[i] << "\n";
    }
    free( stack_syms );

    exit(1);
}   

int foo()
{
    throw std::runtime_error( "hello" );
}   

void bar()
{
    foo();
}

void baz()
{
    bar();
}

int
main()
{
    std::set_terminate( handler );
    baz();
}

giving this output:

samm@macmini ~> ./a.out 
./a.out [0x10000d20]
/usr/lib/libstdc++.so.6 [0xf9bb8c8]
/usr/lib/libstdc++.so.6 [0xf9bb90c]
/usr/lib/libstdc++.so.6 [0xf9bbaa0]
./a.out [0x10000c18]
./a.out [0x10000c70]
./a.out [0x10000ca0]
./a.out [0x10000cdc]
/lib/libc.so.6 [0xfe4dd80]
/lib/libc.so.6 [0xfe4dfc0]
samjmill@bgqfen4 ~> 

assuming you have debug symbols in your binary, you can then use addr2line to construct a prettier stack trace postmortem

samm@macmini ~> addr2line 0x10000c18
/home/samm/foo.cc:23
samm@macmini ~> 

original answer is below


I've done this in the past using boost::error_info to inject the stack trace using backtrace from execinfo.h into an exception that is thrown.

typedef boost::error_info<struct tag_stack_str,std::string> stack_info;

Then when catching the exceptions, you can do

} catch ( const std::exception& e ) {                                                                                                            
    if ( std::string const *stack boost::get_error_info<stack_error_info>(e) ) {                    
        std::cout << stack << std::endl;
    }
}

这篇关于来自未处理异常的c ++堆栈跟踪?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆