60

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 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()?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
unixman83
  • 9,421
  • 10
  • 68
  • 102
  • what about logic exceptions? Are you going to handle them with the error code? – Alessandro Teruzzi Aug 30 '11 at 20:32
  • 1
    @GMan I like C, you are correct. However, std::list and friends are invaluable to have in C – unixman83 Aug 30 '11 at 20:32
  • 2
    @GMan: Not necessarily. Exceptions are extremely inefficient in most cases and are misused very often. There are many cases where you want C++ but don't want exceptions, especially in performance critical paths and in embedded apps. –  Aug 30 '11 at 20:33
  • 7
    @unix: Pick a lanuage: C or C++. The half-breed language invariably creates the ugliest, most broken, and hardest to maintain code. – GManNickG Aug 30 '11 at 20:34
  • 4
    @GMan I only want to die on throw. – unixman83 Aug 30 '11 at 20:35
  • 11
    @Vlad: Extremely inefficient compared to what? And actually, no, not really. GCC has zero-overhead exceptions, which means you only "lose" speed when you throw, which is still better than checking every single error code. – GManNickG Aug 30 '11 at 20:35
  • 15
    @Gman I highly disagree. You can pick subsets of C++ to use and you're not "having no desire to use C++" if you do that. This is what unixman is doing: picking a subset of C++ that excludes exceptions. Lots of people and companies do this. However, I do agree with you here: pick one language, C or C++. They're not nearly the same, and working in both without being more careful than most people have enough knowledge to be is likely to cause misery. – Seth Carnegie Aug 30 '11 at 20:37
  • 3
    @Seth: "Lots of people and companies do this." And lots of people and companies release bad products... Just because you *can* do something doesn't magically make it an equal and justifiable thing compared to the rest. :) I *can* believe the Earth is flat, but I'd still be completely wrong. Yes this case is less objective, but justification is still comparable. – GManNickG Aug 30 '11 at 20:40
  • 14
    @GMan the fact that lots of people use C++ doesn't magically make it bad, does it? Neither does lots of people picking subsets of C++ make that bad just because lots of other people _who may or may not be the same people who chose a subset_ release bad software. Just because you don't embrace every single feature of C++ doesn't mean you shouldn't be using C++. I am not saying it's good to ignore the existence of exceptions, but I am saying that ignoring them doesn't automatically make you an infidel. – Seth Carnegie Aug 30 '11 at 20:41
  • @Seth: I think you lost me on that one, sorry. My point is that saying "lots of people do X" isn't necessarily a justification for doing X. Nor have I called anyone an infidel, but I will stand by my opinion that using subsets of the language produces sub-quality code. – GManNickG Aug 30 '11 at 20:44
  • 1
    @GMan: Compared to no exceptions. Most compilers have zero-overhead exceptions, but throwing them is still extremely expensive compared to returning/checking error code. Plus the code size gets a lot bigger, and that also results in the code not fitting in the cache lines, which degrades performance a lot due to high memory latencies. In general, not using exceptions produces smaller and faster code. Unless you really know how and where to use them, which not many people do. –  Aug 30 '11 at 20:44
  • 2
    @Vlad: "Compared to no exceptions" Then your comparison is vacuous. Of course X compared with not X is slower. That said, you then move on to compare it to error codes, so I'll ignore your first sentence. You do understand the runtime cost of error codes *done correctly*, right? That is, *checking every single function return value*? Exceptions specifically avoid this branch-check overhead, which is, as you ought to know, extremely important in a loop. – GManNickG Aug 30 '11 at 20:47
  • 1
    @GMan While I agree that not using exceptions in c++ wouldn't be fun for me, there are examples that show it works just fine. MS releases some pretty high standard software and they don't use in at least some parts of it. And c++ is complicated enough to warrant not using each and every feature of it. Or am I now also not a "real" c++ programmer because I tend to avoid multiple inheritance if possible? – Voo Aug 30 '11 at 20:48
  • 1
    @Voo: "MS releases some pretty high standard software" Heh, I think we'll disagree right there. :P Of the C++ code I've seen from MS, I've nearly plucked my eyes out. I said nothing about being a "real" programmer, take your silly pathos elsewhere. I've simply stated mixing C and C++ leads to harder to maintain code, because the code no longer conforms to the typical idioms of either language. – GManNickG Aug 30 '11 at 20:51
  • @GMan: Exceptions can speed you up, but in most cases they slow you down. Nevertheless, my point is that C++ without exceptions is still pretty good C++, and so your initial comment is just doesn't make any sense. –  Aug 30 '11 at 20:54
  • 1
    @Voo -- *"MS releases some pretty high standard software"* -- I was always telling people to take a look at MS published code with the sole purpose to teach them **how not to program** – Gene Bushuyev Aug 30 '11 at 20:57
  • 1
    I feel like travelling back in time. I though the *exception* topic was exhausted like a decade ago. – Gene Bushuyev Aug 30 '11 at 20:59
  • @Vlad: *Do* speed you up, mind you. Also your concern about code size: it is true the size increases, but the code never enters cache until an exception is thrown, so no cache misses are introduced. And no, sorry, a bunch of branches (remember, proper error code handling requires every functions return value be checked) simply isn't as fast as not checking anything at all. Exception throws are rare anyway, and often done near user input, where real-time performance doesn't matter. (After all, once you get into deep processing you know the limits of everything.) – GManNickG Aug 30 '11 at 21:04
  • The irony of this question is of course that `die` in Perl actually acts like a thrown exception that can be caught with `eval { ... }`. – Karsten Dec 16 '15 at 07:50

5 Answers5

102

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.

bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • 3
    +1; just don't catch exceptions. That's one of the reasons they're there for. – Seth Carnegie Aug 30 '11 at 20:36
  • 4
    "Note also that stack unwinding will not be performed if an exception is not handled; the program will simply terminate without performing stack unwinding." - this is not guaranteed by the standard. The implementation is allowed to unwind the stack (15.5.1/2). So it's OK for g++, but be careful if the code needs to be at all portable. – Steve Jessop Aug 30 '11 at 22:16
  • 3
    @Steve, yes, all of my advice is G++-specific. After all, the standard doesn't specify _any_ method to completely neuter exceptions :) – bdonlan Aug 30 '11 at 22:32
  • 2
    Sure, I mentioned it just because it's the one option you offer that at first glance might look as though it's applicable to other compilers (and may be, so long as you check their docs - the behavior is implementation-defined, so it has to be documented). – Steve Jessop Aug 30 '11 at 22:55
  • 1
    One comment on "simply not catching exceptions": The Intel compiler prevents automatic vectorizations if exceptions are enabled and may be thrown, wether they are catched or not. So it should be mentioned that completely disabling them can enable the compiler to do more optimizations. – Skym0sh0 Mar 20 '17 at 12:26
  • Will using `-fno-exceptions` compiler option trigger the same performance benefits as marking a function `noexcept` in this case: https://www.youtube.com/watch?v=AG_63_edgUg – user643011 Aug 11 '21 at 08:21
26

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

GManNickG
  • 494,350
  • 52
  • 494
  • 543
21

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.

Community
  • 1
  • 1
Freddie Chopin
  • 8,440
  • 2
  • 28
  • 58
  • I read that this was an issue in FF. https://blog.mozilla.org/nnethercote/2011/01/18/the-dangers-of-fno-exceptions/ But what I don't understand is: In what kind of situation would that cause actual problems? The only situation I can imagine is where you call some STL-function with a catch clause, which calls your code, from which you call STL-code which throws. (Is there even a user-code invoking STL function with catch?) In that situation, }-destructors in your code may not be run, causing memory leaks. Am I missing a bigger problem that may occur? – Caesar Jul 29 '21 at 01:27
11

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.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
2

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

  • 3
    -1 under-descriptive of what happens 'under-the-hood'. Just says do it a certian way, without explanation... – unixman83 Aug 30 '11 at 20:54