禁用 C++ 异常,如何使任何 std::throw() 立即终止?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7249378/
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
Disabling C++ exceptions, how can I make any std:: throw() immediately terminate?
提问by unixman83
This C++ program is a CGI script, I have no desire to deal with exceptions. I'd rather get a marginal performance boost and let the OS (Linux) handle cleanup after the process dies.
这个 C++ 程序是一个 CGI 脚本,我不想处理异常。我宁愿获得边际性能提升,并在进程终止后让操作系统 (Linux) 处理清理。
I am using the Standard C++ Library, and want any function to die
like in Perl: Whenever it throws an exception.Without unwinding, or running any further codein my process.
我正在使用标准 C++ 库,并希望die
Perl 中的任何函数都喜欢:每当它抛出异常时。无需展开或在我的流程中运行任何其他代码。
How does -fno-exceptions work? If I have no catch at all in my code, and basically pretend like exceptions do no exist. but I douse std:: c++ library which canthrow()?
-fno-exceptions 如何工作?如果我的代码中根本没有捕获,并且基本上假装异常不存在。但我确实使用了可以throw() 的std::c++ 库?
回答by bdonlan
Option #1: Simply never catch exceptions.
选项#1:从不捕获异常。
Exceptions don't have much overhead when they're not thrown or caught; if you're throwing and not prepared to catch, well, you're doing to die anyway, so the performance impact at that point is trivial. Note also that stack unwinding will not be performed if an exception is not handled; the program will simply terminate without performing stack unwinding.
当异常没有被抛出或捕获时,它们不会有太多的开销;如果您正在投掷并且不准备接住,那么无论如何您都会死,因此此时对性能的影响是微不足道的。另请注意,如果未处理异常,则不会执行堆栈展开;程序将简单地终止而不执行堆栈展开。
It's important to note that, in G++, exceptions have almost no overhead when not actually thrown. G++ generates extra information sufficient to trace back the execution of the program through the stack, and some extra code to invoke destructors, etc - however none of this extra code or data is ever used until an exception is actually thrown. So you should not see a performance difference between code with exceptions enabled but not used and code with exceptions disabled (through whatever mechanism).
需要注意的是,在 G++ 中,异常在未实际抛出时几乎没有开销。G++ 生成的额外信息足以通过堆栈追溯程序的执行,以及一些额外的代码来调用析构函数等——但是,在实际抛出异常之前,这些额外的代码或数据都不会被使用。因此,您不应看到启用但未使用异常的代码与禁用异常的代码(通过任何机制)之间的性能差异。
Option #2: Pass -fno-exceptions
.
选项#2:通过-fno-exceptions
。
This flag instructs G++ to do two things:
这个标志指示 G++做两件事:
- All exception handling in STL libraries are removed; throws are replaced with
abort()
calls - Stack unwind data and code is removed. This saves some code space, and may make register allocation marginally easier for the compiler (but I doubt it'll have much performance impact). Notably, however, if an exception is thrown, and the library tries to unwind through
-fno-exceptions
code, it will abort at that point, as there is no unwind data.
- 删除了 STL 库中的所有异常处理;throws 被
abort()
调用替换 - 堆栈展开数据和代码被删除。这节省了一些代码空间,并且可能使编译器的寄存器分配稍微容易一些(但我怀疑它会对性能产生很大的影响)。然而,值得注意的是,如果抛出异常,并且库尝试通过
-fno-exceptions
代码展开,它将在该点中止,因为没有展开数据。
This will, effectively, turn all exceptions into abort()
s, as you would like. Note, however, that you will not be allowed to throw
- any actual throw
s or catch
s in your code will result in a compile-time error.
这将有效地将所有异常转换为abort()
s,如您所愿。但是请注意,您将不被允许throw
-代码中的任何实际throw
s 或catch
s 都将导致编译时错误。
Option #3: (Nonportable and not recommended!) Hook __cxa_allocate_exception.
选项 #3:(不可移植且不推荐!)挂钩 __cxa_allocate_exception。
C++ exceptions are implemented using (among others) the __cxa_allocate_exception and __cxa_throw internal library functions. You can implement a LD_PRELOAD library that hooks these functions to abort():
C++ 异常是使用(除其他外)__cxa_allocate_exception 和 __cxa_throw 内部库函数实现的。您可以实现将这些函数挂接到 abort() 的 LD_PRELOAD 库:
void __cxa_allocate_exception() { abort(); }
void __cxa_throw() { abort(); }
WARNING: This is a horrible hack. It should work on x86 and x86-64, but I strongly recommend against this. Notably, it won't actually improve performance or save code space, as -fno-exceptions
might. However, it will allow the throw
syntax, while turning throw
s into abort()
s.
警告:这是一个可怕的黑客。它应该适用于 x86 和 x86-64,但我强烈建议不要这样做。值得注意的是,它实际上不会像-fno-exceptions
可能的那样提高性能或节省代码空间。但是,它将允许throw
语法,同时将throw
s 转换为abort()
s。
回答by GManNickG
-fno-exceptions
turns all standard library throw's into a call to std::abort()
. That handles the part you can't modify directly, the rest is to not use them at all in your code.
-fno-exceptions
将所有标准库 throw 转换为对std::abort()
. 处理你不能直接修改的部分,剩下的就是在你的代码中根本不使用它们。
Of course, I really doubt your justification in doing this. You only "lose" performance when you actually throw, and you're throwing out a significant and helpful bit of the language.
当然,我真的怀疑你这样做的理由。当您实际抛出时,您只会“失去”性能,并且您抛出了该语言的重要且有用的部分。
回答by Freddie Chopin
In case anyone stumbles upon this question, I'd like to correct what @GManNickG and (https://stackoverflow.com/a/7249460/157344) and @bdonlan (https://stackoverflow.com/a/7249442/157344) said in their answers. Unfortunately the part about "-fno-exception" removing all exception handling code and turning all throws into aborts is wrong. Well - partially wrong. This is true when you compile the library in question (libstdc++v3) with this flag, but not true if you use this library (as an .a or .so or .dll or whatever) in your own code compiled with this flag. In the latter case the exception handling code in YOUR code is forbidden, but all the calls to exception handling inside the library remain (because the library was compiled WITHOUTthis flag, with exceptions enabled), so if you use new
then your executable WILLhave exception handling code - the only difference is that you cannot anything about these exceptions with a catch()
(which is forbidden in your code), so all throws effectively end up as abort()
, but only because no one catches them.
如果有人偶然发现这个问题,我想更正@GManNickG 和(https://stackoverflow.com/a/7249460/157344)和@bdonlan(https://stackoverflow.com/a/7249442/157344) 在他们的回答中说。不幸的是,关于“-fno-exception”删除所有异常处理代码并将所有抛出变为中止的部分是错误的。好吧 - 部分错误。当您使用此标志编译有问题的库 (libstdc++v3) 时,这是正确的,但如果您在使用此标志编译的自己的代码中使用此库(作为 .a 或 .so 或 .dll 或其他文件),则不正确. 在后一种情况下,您的代码中的异常处理代码被禁止,但对库内异常处理的所有调用仍然存在(因为库是在没有编译的情况下编译的)这个标志,启用了异常),所以如果你使用,new
那么你的可执行文件将有异常处理代码 - 唯一的区别是你不能用 a catch()
(这是你的代码中禁止的)来处理这些异常,所以所有的抛出都有效地结束了abort()
,但只是因为没有人抓住它们。
回答by Ed Heal
Quote:
引用:
This C++ program is a CGI script, I have no desire to deal with exceptions.
这个 C++ 程序是一个 CGI 脚本,我不想处理异常。
- Then don't. Simple. The exception will get to the top of the stack very quickly.
- 那就别了。简单的。异常会很快到达栈顶。
But I would urge you to do so. To do so means that you are thinking of the things that can go wrong.
但我会敦促你这样做。这样做意味着您正在考虑可能出错的事情。
回答by Ed Heal
Just don't catch them anywhere in your code. In that case, a termination handler will be called and your program will "crash".
只是不要在代码中的任何地方捕获它们。在这种情况下,将调用终止处理程序并且您的程序将“崩溃”。