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.