开发者

Disabling C++ exceptions, how can I make any std:: throw() immediately terminate?

开发者 https://www.devze.com 2023-03-31 16:26 出处:网络
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.

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.

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 code in my process.

How does -fno-exceptions work? If I开发者_StackOverflow中文版 have no catch at all in my code, and basically pretend like exceptions do no exist. but I do use std:: c++ library which can throw()?


Option #1: Simply never catch exceptions.

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).

Option #2: Pass -fno-exceptions.

This flag instructs G++ to do two things:

  1. All exception handling in STL libraries are removed; throws are replaced with abort() calls
  2. 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.

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 throws or catchs in your code will result in a compile-time error.

Option #3: (Nonportable and not recommended!) Hook __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():

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 throws into abort()s.


-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.

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.


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 WITHOUT this flag, with exceptions enabled), so if you use new then your executable WILL have 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.


Quote:

This C++ program is a CGI script, I have no desire to deal with exceptions.

  • 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.


Just don't catch them anywhere in your code. In that case, a termination handler will be called and your program will "crash".

0

精彩评论

暂无评论...
验证码 换一张
取 消