Home > Blockchain >  Would compiler optimization remove try/catch block if catch does nothing?
Would compiler optimization remove try/catch block if catch does nothing?

Time:09-24

I am working with code that has a lot of try catch blocks in but most cases the catch blocks do nothing. As in the code below fib function is throwing invalid_argument exception. The function call in main is in the try block but the catch block does not do anything, except catching the exception.

I am wondering if the compiler might trim away this kind of exception handling during code optimization, or not?

#include <iostream>
#include <exception>


// Declaration for Wmissing-declarations flag
int fib(int);

int fib(int n)
{
    if (n < 0)
        {
            throw std::invalid_argument("Invalid argument");
        }
    if (n == 0 || n == 1)
        return n;
    
    return fib(n-1)   fib(n-2);
}

int main(int argc, char *argv[])
{
    int _number;
    std::cin >> _number;
    try
    {
        std::cout << fib(_number) << std::endl;
    }
    catch(const std::invalid_argument & e)
    {
        
    }
    return 0;
}

Compiling above code with most (all I know) flags turned on, as below, does not show any warning.

g   -o except exceptions.cxx -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

CodePudding user response:

I am wondering if the compiler might trim away this kind of exception handling during code optimization, or not?

TL;DR: No, a compiler cannot and must not optimize away such exception handling.


As mentioned in the comments, an empty catch block is not the same as not having try ... catch blocks.

In your example, although there is no code actually executed in the catch block, the exception thrown when a negative number is passed to the fib function is still caught by that block. At that point, the catch block is conceptually entered, then exited pretty swiftly – passing control (silently) to the code immediately following that empty block.

There will also be some (necessary) stack unwinding, and possibly other 'remedial' actions, performed when that catch block is invoked; thus, even such an empty catch block will still actually catch the relevant exceptions (specified as its arguments).

So, for your code (as-is), entering a test value of -3 will result in normal, successful program termination. On my Windows console (invoked from Visual Studio), I see this:

-3

C:\SGGCode.exe (process 2888) exited with code 0.
Press any key to close this window . . .

However, if I remove the try..catch block, giving the following main (leaving everything else untouched):

int main(int argc, char* argv[])
{
    int _number;
    std::cin >> _number;
    std::cout << fib(_number) << std::endl; // Removed try...catch
    return 0;
}

Then, when I run the program and give the same input, I get this uncaught exception error:

-3

C:\SGGCode.exe (process 2420) exited with code -1073740791.
Press any key to close this window . . .

(Note that -1073740791 is 0xc00004096, which is an uncaught exception error.)


To make things a bit clearer, try adding a line like the following, immediately before the return 0; line in your main:

    std::cout << "See - I'm still here!" << std::endl;

With your empty catch, that will execute; without it, the program will crash before it can get there.

  • Related