C++ try-catch 块是否会降低性能
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16784601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does try-catch block decrease performance
提问by bibbsey
This linkstates,
该链接指出,
To catch exceptions we must place a portion of code under exception inspection. This is done by enclosing that portion of code in a try block. When an exceptional circumstance arises within that block, an exception is thrown that transfers the control to the exception handler. If no exception is thrown, the code continues normally and all handlers are ignored.
为了捕获异常,我们必须将一部分代码置于异常检查之下。这是通过将那部分代码包含在 try 块中来完成的。当该块中出现异常情况时,会抛出异常,将控制权转移到异常处理程序。如果没有抛出异常,代码将继续正常运行并且所有处理程序都将被忽略。
Does it mean that having a try block reduces performance due to the extra task of "inspection" during run time?
这是否意味着由于运行时“检查”的额外任务,使用 try 块会降低性能?
回答by Matthieu M.
TL;DR NO, exceptions are usually faster on the non-exceptional pathcompared to error code handling.
TL;DR NO,与错误代码处理相比,非异常路径上的异常通常更快。
Well, the obvious remark is compared to what ?
那么,明显的评论与什么相比?
Compared to not handling the error, it obviously decrease performance; but is performance worth the lack of correctness ? I would argue it is not, so let us supposed that you meant compared to an error code checked with an if
statement.
与不处理错误相比,它明显降低了性能;但是性能值得缺乏正确性吗?我认为它不是,所以让我们假设您的意思是与使用if
语句检查的错误代码进行比较。
In this case, it depends. There are multiple mechanisms used to implement exceptions. Actually, they can be implemented with a mechanism so close to an if
statement that they end up having the same cost (or slightly higher).
在这种情况下,这取决于。有多种机制用于实现异常。实际上,它们可以通过一种非常接近于if
语句的机制来实现,以至于它们最终具有相同的成本(或略高)。
In C++ though, all major compilers (gcc introduced it in 4.x serie, MSVC uses it for 64 bits code) now use the Zero-Cost Exception Model. If you read this technical paperthat Need4Sleep linked to, it is listed as the table-driven approach. The idea is that for each point of the program that may throw you register in a side-table some bits and pieces that will allow you to find the right catch clause. Honestly, it is a tad more complicated implementation-wise than the older strategies, however the Zero Costname is derived by the fact that it is freeshould no exception be thrown. Contrast this to a branch misprediction on a CPU. On the other hand, when an exception is thrown, then the penalty is huge becausethe table is stored in a cold zone (so likely requires a round-trip to RAM or worse)... but exceptions are exceptional, right ?
但是,在 C++ 中,所有主要编译器(gcc 在 4.x 系列中引入它,MSVC 将它用于 64 位代码)现在都使用零成本异常模型。如果您阅读了 Need4Sleep 链接到的这篇技术论文,它被列为表驱动方法。这个想法是,对于程序的每个点,可能会让您在侧表中注册一些零碎的东西,这将使您能够找到正确的 catch 子句。老实说,它在实现方面比旧的策略稍微复杂一些,但是零成本名称源自它是免费的,不应该抛出异常。将此与 CPU 上的分支预测错误形成对比。另一方面,当抛出异常时,惩罚是巨大的,因为该表存储在冷区(因此可能需要往返 RAM 或更糟)...但例外情况很特殊,对吧?
To sum up, with modern C++ compilers exceptions are faster than error codes, at the cost of larger binaries (due to the static tables).
总而言之,使用现代 C++ 编译器,异常比错误代码更快,代价是更大的二进制文件(由于静态表)。
For the sake of exhaustiveness, there is a 3rd alternative: abortion. Instead of propagating an error via either status or exception, it is possible to abort the process instead. This is only suitable in a restricted number of situations, however it optimizes better than either alternative.
为详尽起见,还有第三种选择:堕胎。不是通过状态或异常传播错误,而是可以中止进程。这仅适用于有限数量的情况,但它比任一替代方案都优化得更好。
回答by Syntactic Fructose
Take a look at Section 5.4 of draft Technical Report on C++ Performancewhich is specifically about the overhead of try-catch statements in c++.
看一下C++ 性能技术报告草案的第 5.4 节, 它专门关于C++中 try-catch 语句的开销。
A little excerpt from the section:
部分摘录:
5.4.1.1.2 Time Overhead of the “Code” Approach
5.4.1.1.2 “代码”方法的时间开销
? On entry to each try-block
? Commit changes to variables enclosing the try-block
? Stack the execution context
? Stack the associated catch clauses
? On exit from each try-block
? Remove the associated catch clauses
? Remove the stacked execution context
? When calling regular functions
? If a function has an exception-specification, register it for checking
? As local and temporary objects are created
? Register each one with the current exception context as it is created
? On throw or re-throw
? Locate the corresponding catch clause (if any) – this involves some runtime check (possibly resembling RTTI checks)
If found, then:
destroy the registered local objects
check the exception-specifications of the functions called in-between
use the associated execution context of the catch clause
Otherwise:
call the terminate_handler6
回答by Tobias Langner
It depends. For exception handling, the compiler has to do something - otherwise it could not do stack unwinding and such. That means yes, exception handling decreases performance - even if the exception is not thrown. How much - this depends on your compilers implementation.
这取决于。对于异常处理,编译器必须做一些事情 - 否则它无法进行堆栈展开等。这意味着是的,异常处理会降低性能——即使没有抛出异常。多少 - 这取决于您的编译器实现。
On the other hand you have to question yourself: If you insert your error handling code yourself, would it really be faster (measure it - don't guess it). Can it do the same as exceptions (exceptions can't be ignored by the client - error codes can - and they can do stackunwinding which error codes can't). Additionally, the code can be written to be more maintainable with exceptions.
另一方面,您必须自问:如果您自己插入错误处理代码,它真的会更快吗(测量它 - 不要猜测它)。它可以做与异常相同的事情吗(客户端不能忽略异常 - 错误代码可以 - 并且他们可以执行错误代码不能的 stackunwinding )。此外,代码可以编写为更易于维护的异常。
Short: unless your code is very very very very very time critical, use exceptions. Even if you decide against them: measure first. One exception to the rule: it's a bad idea to throw exceptions across module boundaries or in a destructor.
简而言之:除非您的代码非常非常非常非常时间关键,否则请使用异常。即使您决定反对它们:先衡量。规则的一个例外:跨越模块边界或在析构函数中抛出异常是一个坏主意。
回答by 6502
It really depends on the specific compiler.
这实际上取决于特定的编译器。
If the compiler prefers to consider exception throwing a really exceptional condition then you can implement a scheme where in case of no exception you have zero-overhead but that, in turn, will cost more time in case of an exception and/or more code size.
如果编译器更喜欢考虑抛出异常的异常条件,那么您可以实施一个方案,在没有异常的情况下,您的开销为零,但反过来,如果出现异常和/或更多代码大小,将花费更多时间.
To implement a zero-overhead approach you can notice that in C++ you cannot dynamically change code so once you know what is the stack frame and the return address it's fixed what are the objects that must be destroyed in case of unwinding or if there is an exception handling code section. The code for throwing an exception could therefore check a global table of all function call sites to decide what should be done.
要实现零开销方法,您会注意到在 C++ 中您不能动态更改代码,因此一旦您知道堆栈帧和返回地址是什么,它就固定了在展开的情况下必须销毁的对象是什么,或者如果有异常处理代码部分。因此,用于抛出异常的代码可以检查所有函数调用站点的全局表来决定应该做什么。
On the other side you can make exception throwing faster by preparing the list of objects to be explicitly destroyed and the address of the exception handling code during normal execution. This will make regular code slower, but exception handling faster and also I'd say code a bit smaller.
另一方面,您可以通过在正常执行期间准备要显式销毁的对象列表和异常处理代码的地址来更快地抛出异常。这将使常规代码变慢,但异常处理速度更快,而且我会说代码更小。
Unfortunately there is no standard way in C++ to completely give up exception support, so something has to be paid to this possibility: the standard library throws exceptions and any code that calls unknown code (e.g. using a function pointer or calling a virtual method) must be prepared to handle an exception.
不幸的是,在 C++ 中没有完全放弃异常支持的标准方法,因此必须为这种可能性付出代价:标准库抛出异常并且任何调用未知代码的代码(例如使用函数指针或调用虚拟方法)必须准备好处理异常。
回答by CodeRider
I would recommend adding try catch in functions which does memory allocation, deletion, calling another complex functions etc. Actually performance wise try catch adds a little bit of overhead.
我建议在执行内存分配、删除、调用另一个复杂函数等的函数中添加 try catch。实际上,性能明智的 try catch 会增加一点开销。
But considering the merit of catching the unknown exceptions it is very helpful. Good programming practices always recommend adding some kind of exception handling in your code unless you are an exceptional programmer.
但是考虑到捕获未知异常的优点,它非常有帮助。良好的编程习惯总是建议在您的代码中添加某种异常处理,除非您是一名出色的程序员。
I wonder why you are so concerned about small performance issue than the entire program being stuck with an exception.
我想知道为什么你如此关心小的性能问题而不是整个程序被一个异常卡住。