小智 24
不,它是非常可怕的,我不明白为什么你需要在异常本身的调用堆栈 - 我发现异常原因,行号和初始异常发生的代码的文件名已经足够了.
话虽如此,如果你真的必须有一个堆栈跟踪,那么要做的是在异常抛出站点生成调用堆栈信息ONCE.没有一种可移植的方法可以做到这一点,但使用像http://stacktrace.sourceforge.net/这样的东西和VC++的类似库应该不会太困难.
Mic*_*yan 22
你在做什么不是好习惯.原因如下:
这是不必要的.
如果在调试模式下编译项目以便生成调试信息,则可以轻松地在调试器(如GDB)中进行异常处理的回溯.
这很麻烦.
这是你必须记住添加到每个功能的东西.如果你碰巧错过了一个函数,那可能会引起很多混乱,特别是如果那是导致异常的函数的话.任何看你的代码的人都必须意识到你在做什么.另外,我敢打赌你使用了像__FUNC__或__FUNCTION__或__PRETTY_FUNCTION__之类的东西,遗憾的是这些都是非标准的(C++中没有标准方法来获取函数的名称).
这很慢.
C++中的异常传播已经相当慢,添加此逻辑只会使代码路径变慢.如果您使用宏来捕获和重新抛出,这不是问题,您可以轻松地删除捕获并重新抛出代码的发行版本.否则,性能可能是个问题.
好的做法
虽然捕获和重新抛出每个函数来构建堆栈跟踪可能不是一个好习惯,但最好附加最初抛出异常的文件名,行号和函数名.如果你在BOOST_THROW_EXCEPTION中使用boost :: exception,你将免费获得这种行为.将解释性信息附加到您的异常也有助于调试和处理异常.也就是说,所有这些都应该在异常构建时发生; 一旦它被构造,它应该被允许传播到它的处理程序......你不应该重复捕获和重新抛出超过严格必要的.如果您需要捕获并重新抛出特定功能以附加一些关键信息,那很好,
一个可能更优雅的解决方案是构建一个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.aspx和http://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 次 |
| 最近记录: |