C++中异常的调用栈

Igo*_*Oks 30 c++ callstack exception try-catch

今天,在我的C++多平台代码中,我对每个函数都进行了尝试.在每个catch块中,我将当前函数的名称添加到异常并再次抛出,以便在最上面的catch块(我最终打印异常的详细信息)中,我有完整的调用堆栈,这有助于我跟踪异常的原因.

这是一个好习惯,还是有更好的方法来获取异常的调用堆栈?

小智 24

不,它是非常可怕的,我不明白为什么你需要在异常本身的调用堆栈 - 我发现异常原因,行号和初始异常发生的代码的文件名已经足够了.

话虽如此,如果你真的必须有一个堆栈跟踪,那么要做的是在异常抛出站点生成调用堆栈信息ONCE.没有一种可移植的方法可以做到这一点,但使用像http://stacktrace.sourceforge.net/这样的东西和VC++的类似库应该不会太困难.

  • @Neil:从另一个角度来看,我发现堆栈跟踪是不可或缺的.@Igor:要在gcc中生成堆栈跟踪,http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes,我确定windows有类似的东西.无论如何,围绕每个功能包裹这些块确实是"非常可怕". (14认同)
  • 我说的是一个大型项目.这种机制帮助我多次看到引起异常的全流程.为什么它如此可怕,如果它节省了我很多调试时间? (10认同)
  • @Igor我们其他人当然只在小规模项目上工作?它可以节省你的调试时间(虽然你花了很多时间调试你有其他问题)但它大大降低了你的代码的可维护性和可读性(至少对我来说)更为重要. (2认同)
  • 是的,堆栈跟踪是好的,没有自己的构建是不可维护的.至少在Windows上,当你捕获异常时,你调用`GetExceptionInformation`,它给你一个`CONTEXT`结构传递给`StackWalk64`. (2认同)
  • @Ben您支付的最高价格是便携性,在这种情况下是一种重新计算. (2认同)

Mic*_*yan 22

你在做什么不是好习惯.原因如下:

这是不必要的.
如果在调试模式下编译项目以便生成调试信息,则可以轻松地在调试器(如GDB)中进行异常处理的回溯.

这很麻烦.
这是你必须记住添加到每个功能的东西.如果你碰巧错过了一个函数,那可能会引起很多混乱,特别是如果那是导致异常的函数的话.任何看你的代码的人都必须意识到你在做什么.另外,我敢打赌你使用了像__FUNC__或__FUNCTION__或__PRETTY_FUNCTION__之类的东西,遗憾的是这些都是非标准的(C++中没有标准方法来获取函数的名称).

这很慢.
C++中的异常传播已经相当慢,添加此逻辑只会使代码路径变慢.如果您使用宏来捕获和重新抛出,这不是问题,您可以轻松地删除捕获并重新抛出代码的发行版本.否则,性能可能是个问题.

好的做法
虽然捕获和重新抛出每个函数来构建堆栈跟踪可能不是一个好习惯,但最好附加最初抛出异常的文件名,行号和函数名.如果你在BOOST_THROW_EXCEPTION中使用boost :: exception,你将免费获得这种行为.将解释性信息附加到您的异常也有助于调试和处理异常.也就是说,所有这些都应该在异常构建时发生; 一旦它被构造,它应该被允许传播到它的处理程序......你不应该重复捕获和重新抛出超过严格必要的.如果您需要捕获并重新抛出特定功能以附加一些关键信息,那很好,


Sco*_*ord 7

一个可能更优雅的解决方案是构建一个Tracer宏/类.所以在每个函数的顶部,你写了类似的东西:

TRACE()
Run Code Online (Sandbox Code Playgroud)

宏看起来像:

Tracer t(__FUNCTION__);
Run Code Online (Sandbox Code Playgroud)

并且类Tracer在构造时将函数名称添加到全局堆栈,并在销毁时自行删除.然后该堆栈始终可用于记录或调试,维护更简单(一行),并且不会产生异常开销.

实现的示例包括像http://www.drdobbs.com/184405270, http://www.codeproject.com/KB/cpp/cmtrace.aspxhttp://www.codeguru.com/cpp/vs /debug/tracing/article.php/c4429.此类Linux函数http://www.linuxjournal.com/article/6391可以更原生地执行此操作,如此Stack Overflow问题所述:如何在我的gcc C++应用程序崩溃时生成堆栈跟踪.ACE的ACE_Stack_Trace也值得关注.

无论如何,异常处理方法粗糙,不灵活且计算成本高.如果需要,类构造/宏解决方案要快得多,并且可以针对发布版本进行编译.


归档时间:

查看次数:

24282 次

最近记录:

11 年,4 月 前