With "-fno-exceptions", what happens with "new T"? - c++

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?

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

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

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.

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.

Related

Convert NULL pointer access to C++ exception under Linux/GCC

Is there any way to convert a NULL pointer access into a C++ exception under Linux ? Something similar to the NullPointerException in Java. I hope the following program would return successfully, instead of crash (assume the compiler cannot figure out this NULL pointer access during compile time):
class NullPointerException {};
void accessNullPointer(char* ptr) {
*ptr = 0;
}
int main() {
try {
accessNullPointer(0);
} catch (NullPointerException&) {
return 1;
}
return 0;
}
I'm not expecting any standard way of doing it, since NULL pointer access under C++ is undefined-behavior, just want to know how to get it done under x86_64 Linux/GCC.
I did some very primitive research in this, it might be possible:
When a NULL pointer is access under Linux, a SIGSEGV will be generated.
Inside the SIGSEGV handler, the program's memory and register information will be available (if sigaction() is used to register the signal handler). The instruction which caused the SIGSEGV is also available if the program is disassembled.
Modify the program's memory and/or register, and create/fake an exception instance (maybe by invoking the low level unwind library functions, like _Unwind_RaiseException, etc.)
Finally return from the signal handler, hope the program would start a C++ stack unwinding process like a normal exception was thrown.
Here's a quote from GCC's man page (-fnon-call-exceptions):
Generate code that allows trapping instructions to throw exceptions. Note that this requires platform-specific runtime support that does not exist everywhere. Moreover, it only allows trapping instructions to throw exceptions, i.e. memory references or floating point instructions. It does not allow exceptions to be
thrown from arbitrary signal handlers such as "SIGALRM".
It seems this "platform-specific runtime" is exactly what I want. Anyone knows such a runtime for Linux/x86_64 ? Or give me some information on how to implement such a runtime if no such runtime already exists ?
I want the solution to work in multi-threaded program as well.
No, there's no good way to do that, and there shouldn't be. Exceptions are thrown by a throw statement in source code. That's important for reasoning about exception safety: you can look at the code and see the places where exceptions can be thrown and, perhaps more important, you can look a the code and see the places where exceptions will not be thrown. If pretty much anything you do can throw an exception it becomes very difficult to write exception-safe code without cluttering it with catch clauses. Microsoft tried this in their early C++ compilers: they piggybacked C++ exception handling on top of their OS's structured exceptions, and the result was a disaster.
Register an alternative signal stack with signalaltstack().
The 3rd argument to a signal handler handler registered with the SA_SIGINFO is a pointer to a ucontext_t which contains the saved register. The signal handler should adjust this to simulate a call to a function. That function can then throw the exception.
Potential complications include the need to preserve the value of callee saved registers, the red-zone on x86-64 (which can be disabled) and the return address register on some ISAs, such as ARM.

lldb - breaking before C++ exception thrown

In lldb I'd like to break before C++ throws the exception, on when the actual signal is generated. I'd like to do this for any type of exception.
The following command will break on the C++ throw catcher
break set -E c++
I'd like to break on the cause of the exception and ignore the C++ throw/catch as if the application was crashing. I'd also like to do this for applications without source.
Is there any lldb voodoo I can use here?
I'm not entirely sure what you are asking.
Exceptions throws in C++ do two things, create the exception object, and then directly call some runtime routine (__cxa_throw on most Unixen) to implement the unwinding. The latter is the point where the exception breakpoint stops. There isn't any more preliminary than this that you could hook onto.
You could try breaking when the exception object is allocated. On OS X & Linux this is __cxa_allocate_exception, but I don't know if that will always get called or if there are alternate ways to make the exception... I don't see how you would gain much from that, however, it's just a couple of instructions later that you'll see the call to the throw method.
But maybe if you describe the problem you are actually trying to solve, we can answer more helpfully...

-fno-exceptions for some libraries?

This is somewhat similar to "Disabling C++ exceptions, how can I make any std:: throw() immediately terminate?." I would like my program to terminate whenever an exception is thrown out of the STL.
The problem is as follows: I am writing a library which is then loaded as a shared object and executed by a program I don't have control over. Unfortunately this program runs everything in a big try bock so that I don't get a stack trace/core dump if an error is thrown, rendering the ::at class of function's out of range error useless.
This sounds like the ideal use case for -fno-exceptions, but I can't just use -fno-exceptions, because boost_log and the program that calls me both have exception handling defined in their headers giving me compile errors with -fno-exceptions.
Is there a way to enable -fno-exceptions only for stl exceptions?
With C++11, the easiest way to do is to add noexcept to the signature of the top level function that is called from your shared library:
void called_func() noexcept;
This will cause any unhandled exceptions in the called_func stack frame (or below if they are not handled) to terminate the execution of the program.

Find object throwing std::out_of_range

A program of mine throws a std::out_of_range. I know the reason for that, I'm accessing a vector with index -1 somewhere. What I don't know is the name of the vector (variable name) and location in the code. The error message produced by my program looks like this:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
zsh: abort (core dumped) ./main.x config.cfg
whereas the error message produced by the code of some other guy (he uses g++ too) and posted in the question C++ accessing vector looks like this:
Error for vec.at(i).setVec(tmp);
Error is: terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
I.e. he is told the name of the variable. My question is:
Is there any way to tell g++/gcc to give me the extended info? Maybe even include line numbers (don't know whether that's possible but hey, a guy can dream ;) ).
Just for funsies I ran my program in gdb with the catch thrown option (I might add, I have near zero experience in using an actual debugger) which didn't tell me anything new either, in fact, it didn't tell me that the error was due to a std::out_of_range exception.
Btw, my compiler flags (for debug) are:
CFLAGS = --exceptions -I$(ROOTSYS)/include --std=c++11 -Wall -g -O0 -fno-inline -fno-eliminate-unused-debug-types
After hitting the breakpoint enter bt (backtrace) command in the gdb shell. This will print the stack trace (a sequence of function calls leading to the error).
To get the variable name you can now use up command to navigate upwards in the stack and see what variables where used in each of those functions.
Put a breakpoint on std::out_of_range::out_of_range. An exception object, like all C++ objects, starts its life after its constructor exits.
[EDIT]
Comment made it clear: the problem the string produced by std::out_of_range::what(). That's implementation-defined. Obviously in your case it's composed from __FUNCTION__, a GCC macro which names the current (i.e. throwing) function. But such a function only knows this, i.e. the pointer to the current object and not its name. In the other case, the objects name is retrieved via some other method, not std::out_of_range::what().
To avoid hitting a break point at every exception thrown and stop only atstd::out_of_range use this command in gdb:
catch throw std::out_of_range
Then run the commad bt or where when the breack point is hit to see where in the code the exception was thrown

How can I debug St9bad_alloc failures in gdb in C?

I have a program failing with:
terminate called after throwing an instance of 'std::bad_alloc'
what(): St9bad_alloc
I imagine it's something to do with malloc/free, but I don't know which one.
What breakpoint can I in gdb set that will break on the error so that I can view a stack trace?
The program is a combination of C and C++, compiled with gcc 3.4.2.
It is not really malloc/free which causes the exception, it is "new" which is definitely in C++ part of your application. It looks like you are providing a parameter which is too big for "new" to allocate.
'std::bad_alloc' is caused by the following code for example:
int * p = new int[50000000];
What does backtrace says when you load crash dump into gdb?
If you cannot generate dump, you can ask GDB to stop when exception is thrown or caught.
Unfortunately, some versions of GDB support only the following syntax:
catch throw
which allows you to break application when any exception is thrown.
However, in help you see that it should be possible to run
catch throw std::bad_alloc
in newer versions.
And don't forget that:
(gdb) help catch
is a good source for other useful information.
It's quite possible that this happens due to some memory being overwritten, thus corrupting the memory allocation system's state (which is generally kept either before or after the memory blocks returned to the application).
If you have the possibility (i.e., you're on x86 Linux), run your program in Valgrind, it can often show you exactly where the corruption happens.
I have had this when trying to read in a file that doesn't exist... I'd try to create an internal buffer for the file contents, but because the file didn't exist, my creation of the buffer screwed up.
int lenth_bytes;
length_bytes = in_file.tellg();
new char [length_bytes]; // length_bytes hadn't been initialised!!!!
Remember kids, always initialise your variables :D and check for zero cases.