With "-fno-exceptions", what happens with "new T"?
C++ExceptionC++ Problem Overview
I was wondering, will new T
still throw bad_alloc
if I compile my program using the -fno-exceptions
option to disable exception handling?
Or will the compiler (GCC and clang support that option) implicitly transform the use of new T
to new (nothrow) T
?
C++ Solutions
Solution 1 - C++
The way I understand it, operator new
is defined by libstdc++. If you now compile your own code with -fno-exceptions
, you cannot catch any exceptions, but you will still be linking against the normal version of libstdc++, which does throw an exception.
So yes, new T
will throw an exception, even with -fno-exception
.
However, if you compiled libstdc++ with -fno-exception
as well, things become different. Now, new T
cannot throw an exception but, if I read the libstdc++ manual right it will call abort()
instead.
It seems that, if you want your new T
to return NULL on failure, the only way is to explicitely specify nothrow
...
Solution 2 - C++
I can't give a definitive answer to all the perks around -fno-exceptions, just the observations on a 32 bit linux machine, gcc 4.5.1 - bad_alloc is thrown with and without -fno-exceptions
[21:38:35 1 ~/tmp] $ cat bad_alloc.cpp
int main()
{
char* c = new char[4000000000U];
}
[21:38:58 1 ~/tmp] $ g++ bad_alloc.cpp
[21:39:06 1 ~/tmp] $ ./a.out
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
[21:39:07 1 ~/tmp] $ g++ -fno-exceptions bad_alloc.cpp
[21:39:16 1 ~/tmp] $ ./a.out
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
Solution 3 - C++
It's not a definitive answer, but the GCC Manual (see the section "Doing Without") has this:
> Before detailing the library support
> for -fno-exceptions
, first a passing
> note on the things lost when this flag
> is used: it will break exceptions
> trying to pass through code compiled
> with -fno-exceptions
whether or not
> that code has any try or catch
> constructs. If you might have some
> code that throws, you shouldn't use
> -fno-exceptions
.
The way I read that, you might have to explicitly ask for the nothrow version of new
to be completely safe.
Solution 4 - C++
In many exception-handling systems, if routine "foo" calls "bar", which in turn calls "moo", and "moo" throws an exception, the only way that exception can cleanly make it back to "foo" is if "bar" has code to handle the exception. Even if "bar" is going to let the exception propagate uncaught, it will generally have to ensure that its local variables get properly destroyed before execution is allowed to leave scope. This will require adding extra code to "bar"; in most systems, some of that code will have to execute even if no exception is thrown.
BTW, on some ARM processors like the Cortex M3, or like the Arm7 running in ARM mode, if the caller is also going to be running in ARM mode, one could allow for exceptions without any execution-time cost by having a "normal" subroutine return go to LR+4 (four bytes beyond the normal return address) and have an exceptional exit go to LR (which would then be a 4-byte branch instruction). Such behavior would be contrary to normal practice on the ARM, though, and such a design would not port nicely to the Cortex M0.