Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are compilers allowed to optimize-out exception throws?

We have been discussing this topic today at work, and none of us could come up with a definitive answer about that question. Consider the following situation:

int foo()
{
  int err;

  err = some_call(1);

  if (err != 0)
    return err;

  err = some_call(2);

  if (err != 0)
    return err;

  err = some_call(3);

  if (err != 0)
    return err;

  err = some_call(4);

  if (err != 0)
    return err;

  bar();

  return err;
}

There is a lot of code repetition. Obviously, this could be factorized with a macro, sadly not with a template (because of the return clause). Or at least not directly.

Now the question is, if we were to replace those return error codes with exceptions, and catching those exceptions right away, are compilers allowed and smart enough to detect the pattern and avoid throwing exceptions altogether ?

Here is an illustration of what I mean:

int foo()
{
  try
  {
    // some_call now throws a ErrorReturned exception that contains the error code upon failure.
    some_call(1);
    some_call(2);
    some_call(3);
    some_call(4);
  }
  catch (ErrorReturned& ex)
  {
    return ex.error_code();
  }

  bar();

  return 0;
}

Now, there is no current performance issue and so yes, we don't need to optimize or even care about that. This is more to understand what compilers are allowed to do.

In short so, is it a "good" practice and if so, can compilers optimize that by not throwing exceptions at all ? (Assuming the exception construction has no side effect)

like image 860
ereOn Avatar asked Oct 15 '13 12:10

ereOn


1 Answers

"Are compilers smart enough" seems to hint that Exceptions don't serve a purpose in your project and, if that's the case, you shouldn't use them in the first place (unless of course you actually have the possibility of getting an exception).

Short-answer: No, compilers will not remove your exceptions / exception handling based on the pattern you're using them.

When you use a try/catch, the exception it handles is added to the main exception table; this table can be monitored, hooked into, added on and removed from. Just because you catch the exception right away doesn't mean other things aren't happening with it as well.

Side Source:
A paper was written on Optimizing Away C++ Exception Handling that outlines all (almost all) current implementations of optimizations pertaining to exceptions. Throughout it, it shows that at the current time they are not stripped at compile-time but optimizations are made to them. The paper itself recommends enhancements to EH (Exception Handling) to remove the unnecessary exceptions and, overall, is a pretty good read.

UPDATE (additional sources)
Looking further into the topic, the GCC compiler appears to not optimize away exceptions; however, it does offer an option to do so: -fno-exceptions. This option will remove all exceptions and directly replace them with abort() calls.

Another source (here on StackOverflow) doesn't directly mention "removing exceptions" but does outline the two optimizations made to exceptions, setjmp/longjmp and Zero-Cost. It can be inferred by the highlighting of the actual enhancements without mention of "completely removing the exception" that there is no such optimization (yet, at least with the mentioned compilers). Another source with more detailed info on these optimizations can be found here.

like image 67
newfurniturey Avatar answered Oct 26 '22 02:10

newfurniturey