重新抛出异常保留回溯

时间:2018-09-18 08:01:49

标签: c++ debugging exception gdb

我需要捕获一些“致命的” C ++ exception,然后刷新日志并使用自己的回溯丢弃前一个

但是,我当前的解决方案(正确)显示了错误的堆栈跟踪。

#include <exception>
#include <iostream>

void fatal(const std::exception & E)
{
    // do - something - extremely - important
    throw E;
}

int foo()
{
    throw std::runtime_error("yet another foo function");
}

int main()
{
    try
    {
        return foo();
    }
    catch (const std::exception & E)
    {
        fatal(E);
    }
    return -1;
}

程序被包裹

  $ cat ./backtrace
  backtrace
  quit

  $ ulimit -c unlimited
  $ ./a.out
  $ gdb -q ./a.out core -x ./backtrace

结果是

  

程序以信号SIGABRT终止,异常终止。

     

............................................... ...

     

/ usr / lib / x86_64-linux-gnu / libstdc ++。so.6中std :: terminate()()中的4 0x00007f496eb53701

     

/ usr / lib / x86_64-linux-gnu / libstdc ++。so.6中__cxa_throw()中的5 0x00007f496eb53919

     

6 0x0000000000400d71致命(std :: exception const&)()

     

main()中的7 0x0000000000400e5b

我认为(通过const ref)抛出异常是一种传递原始回溯的技术。我对回溯foo()而不是fatal()感兴趣。

3 个答案:

答案 0 :(得分:4)

我不确定您要在这里完成什么,但是要抛出异常,您需要编写throw;(不带参数),throw E;将通过复制构造它来抛出一个新的异常实例从现有对象中获取。

虽然不确定其中任何一个如何对堆栈跟踪有帮助。 “通过原始回溯” 并没有多大意义,因为C ++中的异常不包含任何回溯,并且在您的catch块调用堆栈时,该清理已被清除。

答案 1 :(得分:3)

使用您的脚本:

backtrace
quit

...您只会在下级即将退出时(或在使用核心文件(例如在示例中,当它已经退出时))看到堆栈跟踪,因为您没有告诉gdb在任何地方停止

另一种方法是使用gdb catch throw命令以及一些脚本。这样,您可以在每个throw处捕获堆栈跟踪。您可以这样操作:

(gdb) catch throw
Catchpoint 1 (throw)
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
> silent
> backtrace
> continue
> end

这将在每个throw停止并打印回溯。但是,您确实不想从fatal框架打印堆栈跟踪。为此,您可以使用gdb便捷函数并使捕捉点成为条件:

(gdb) cond 1 $_any_caller_matches("fatal", 10)

(“ 10”仅是将fatal与处理投掷的C ++库内部分隔开多少帧的猜测。)

答案 2 :(得分:1)

这个问题已经回答了,但是我想补充一点,就是可以在标准C ++ 11 中创建适当的回溯记录:

使用std::nested_exceptionstd::throw_with_nested

在StackOverflow herehere上对此进行了描述,如何通过简单的方法在代码内获取异常的回溯,而无需调试器或繁琐的日志记录编写适当的异常处理程序,它将抛出嵌套异常。 但是,这要求您将希望跟踪的所有函数包装到try/catch块中,但是它使您可以对发生的事情和打印的信息进行大量的自定义。由于您可以使用任何派生的异常类执行此操作,因此可以向此类回溯中添加很多信息!

您还可以查看我的MWE on GitHub或我的"trace" library,其中回溯显示如下:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"