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

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.

Related

Is signal.h a reliable way to catch null pointers?

i am currently writing a small VM in C/C++. Obviously i can't let the whole VM crash if the user dereferences a null pointer so i have to check every access which is becoming cumbersome as the VM grows and more systems are implemented.
So i had an idea: write a signal handler for sigsegv and let the OS do its thing but instead of closing the program call the VM exception handler.
It seems to work (with my very simple test cases), but i didn't find anything guaranteeing a Sigsegv being thrown on null-derefs nor the handler being called for OS generated signals.
So my question is:
Can i count on signal.h on modern destkop OSes (i don't really care if it's not standard on doesn't work on something other than linux/win: it's a pet project). Are there any non trivial stuff i should be aware of (obscure limitations of signal(...) or longjmp(...) ?)
Thank you !
Here is the pseudo implementation:
/* ... */
jmp_buf env;
/* ... */
void handler(int) {
longjmp(env, VM_NULLPTR);
}
/* ... */
if(setjmp(env)) {
return vm_throw("NullPtrException");
}
switch(opcode) {
/* instructions */
case INVOKE:
*stack_top = vm_call(stack_top->obj); // don't check anything in the case where stack_top or stack_top->obj is null handler() will be called an a "NullPtrException" will be thrown
break;
/* more instructions */
}
/* ... */
Note : i only need to check nulls, garbage (dangling) pointers are handled by the GC and should not happen.
Calling longjmp() from a signal handler is only safe if the signal handler is never invoked from async signal unsafe code. So for example if you might receive SIGSEGV by passing a bad pointer to any of the printf() family of functions, you cannot longjmp() from your signal handler.
Can i count on signal.h on modern destkop OSes
You can count on it in the sense that the header, and the functions within will be available on all standard compliant systems. However, exactly what what signals are thrown and when is not consistent across OSes.
On windows, you may need to compile your program with cygwin or similar environment to get the system to raise a segmentation fault. Programs compiled with visual studio use "structured exceptions" to handle invalid storage access.
Is signal.h a reliable way to catch null pointers?
There are situations where null pointer dereference does not result in the raising a segmentation fault signal, even on a POSIX system.
One case might be that the compiler has optimized the operation away, which is typical for example in the case of dereferencing a null pointer to call a member function that does not access any data members. When there is no invalid memory access, there is no signal either. Of course, in that case there won't be a crash either.
Another case might be that address 0 is in fact valid. That's the case on AIX, which you don't care about. It is also the case on Linux, which you do care about, but not by default and you might choose to not care about the case where it is. See this answer for more details.
Then there is your implementation of the signal handler. longjmp is not async signal safe, so if the signal was raised while another non-safe operation was being performed, the interrupted operation may have left your program in an inconsistent state. See the answer by John Zwinck and the libc documentation for details.

MS Visual Studio 2005 C++ exception handling

I have a C++ application built in MS Visual Studio 2005 that links to a 3rd party library. For a certain input, the application crashes in the 3rd party library (apparently somewhere in realloc.c; so has to be a memory issue of some kind). I ran in release because the input is huge. So I ran until it crashes and then choose to debug. While I separately debug the guilty function, I was hoping to use some exception handling to prevent the application from crashing and instead exit cleanly. So I used something like:
try {
//- call 3rd party application function that fails
}
catch(...) {
//- handle exception or whatever
Logger::Fatal("Fatal error: Exiting...");
return false;
}
But to my surprise the application still crashes! I was expecting to see it display the error message since I've presumably caught all exceptions with the ellipsis (...); what am I missing here? I even tried setting /EHca (was /EHsc) in Project Properties -> C/C++ -> Code Configuration -> Enable Exception Handling. On a related note about what might be causing the problem, is the following usage correct?
my_class* mc[] = {nil, nil, nil};
for (int i = 0; i < 3; ++i) {
mc[i] = new my_class();
//-Do stuff with mc[i]
if (mc[i] != nil) {
delete mc[i];
mc[i] = nil;
}
}
The failure to get the exception handling working is rather puzzling. I would certainly appreciate ideas/insights from the C++ gurus out there. BTW, the same problem also occurs on Linux (RHEL5) but I am currently trying to get the exception handling to work on Windows.
NOTE: When I let it debug after the crash. I do get an "Access violation..unable to read location" message. With this updated info, I was hoping something in C++ would still work on both Windows & Linux for such crashes.
Have you tried catching the crash by calling SetUnhandledExceptionFilter?
As Miguel suggested, a correct way to solve your problem is probably to use SetUnhandledExceptionFilter. But I'd like to explain your phenomena in details nevertheless.
First of all, not all the program "crashes" are related to exceptions. For instance, CRT may trigger program termination upon errors, such as invalid element access in a vector, or a pure virtual destructor call. If you want to cover those cases as well - see set_unexpected, set_terminate and etc.
Besides of this, catch block may only catch exceptions thrown from the appropriate code block. OTOH there may be functions that are called elsewhere, such as window procedures (if applicable), other threads and etc.
Now, regarding your problem. Let's first realize why things like catch(...) may catch things like access violation, and etc, and why this does not always happen (like in your case).
Windows provides its own exception handling mechanism - SEH, structured exception handling. It's far superior to C++ exception handling. In addition hardware interrupts (caused by CPU) are automatically "converted" into SEH exceptions, so that the code that uses SEH handles both software exceptions and hardware failures.
Microsoft C++ compilers actually implement C++ exceptions via SEH. That is throw is implemented via RaiseException with specifying C++ - specific exception code and parameters, catch is a C++ - specific wrapper for __except, and for every object with destructor the compiler generates something similar to __finally block. And this also works vice-versa. When a non-C++ exception is raised - the same code generated for C++ exceptions is executed.
In addition there are so-called compiler exception handling options that affect both the compiler exception handling code generation, and its behavior in runtime. They are called exception handling models:
synchronous. The compiler generates a code that is guaranteed to work correctly only if exceptions are raised explicitly. This includes throw statments, and all the "foreign" functions whose code is not visible to the compiler (in some variations - only C++ foreign functions). In particular reading from memory is considered "safe".
asynchronous. The compiler is not allowed to assume anything about where exceptions may arise. Hence it generates the code that should work correctly even if exception is arises from accessing a memory address.
In addition, CRT code that's invoked in catch (...) deliberately ignores non-C++ exceptions, unless asynchronous EH model is choosen.
So that if you want catch (...) to catch non-C++ exceptions - you must choose the asynchronous EH model.
Once I've written an article on the codeproject, after I had a related problem in driver development. It explains all this in details.

Is it "legal" for C++ runtime to call terminate() when the C++ code is used inside some non-C++ program?

In certain cases - especially when an exception escapes a destructor during stack unwinding - C++ runtime calls terminate() which must do something reasonable post-mortem and then exit the program. When a question "why so harsh" arises the answer is usually "there's nothing more reasonable to do in such error situations". That sounds reasonable if the whole program is in C++.
Now what if the C++ code is in a library and the program that uses the library is not in C++? This happens quite often - for example I might have a native C++ COM component consumed by a .NET program. Once terminate() is called inside the component code the .NET program suddenly ends abnormally. The program author will first of all think "I don't care of C++, why the hell is this library make my program exit?"
How do I handle the latter scenario when developing libraries in C++? Is it reasonable that terminate() unexpectedly ends the program? Is there a better way to handle such situations?
Why is the C++ runtime calling terminate()? It doesn't do it at random, or due to circumstances which cannot be defined and/or avoided when the code is written. It does it because your code does something that is defined to result in a call to terminate(), such as throwing an exception from a destructor during stack unwinding.
There is a list in the C++ standard of all the situations which are defined to result in call to terminate(). If you don't want terminate() to be called, don't do any of those things in your code. The same applies to unexpected(), abort(), and so on.
I don't think this is any different really from the fact that you have to avoid undefined behavior, or in general avoid writing code which is wrong. You also have to avoid behavior which is defined but undesirable.
Perhaps you have a particular example where it is difficult to avoid a call to terminate(), but throwing an exception from a destructor during stack unwinding isn't it. Just don't throw exceptions out of destructors, ever. This means designing your destructors such that if they do something which might fail, the destructor catches the exception and your code continues in a defined state.
There are some situations where your system will impolitely hack your process away at the knees because of something that your C++ code does (although not by calling terminate()). For example, if the system is overcommitting memory and the VMM can't honour the promises malloc/new have made, then your process might be killed. But that's a system feature, and probably applies equally to the other language that's calling your C++. I don't think there's anything you can (or need to) do about it, as long as your caller is aware that your library might allocate memory. In that circumstance it's not your code's fault the process died, it's the defined response of the operating system to low-memory conditions.
I think the more fundamental issue isn't specifically what terminate does, but the library's design. The library may be designed to be used only with C++ in which case exceptions can be caught and handled as appropriate within the app.
If the library is intended to be used in conjunction with non-C++ apps, it needs to provide an interface that ensures no exceptions leave the library, for example an interface that does a catch(...).
Suppose you have a function in C++ called cppfunc and you are invoking it from another langugage (such as C or .NET). I suggest you create a wrapper function, let's say exportedfunc, like so:
int exportedfunc(resultype* outresult, paramtype1 param1, /* ... */)
{
try {
*outresult = cppfunc(param1,param2,/* ... */);
return 0; // indicate success
}catch( ... ) { // may want to have other handlers
/* possibly set other error status info */
return -1; // indicate failure
}
}
Basically, you need to ensure that exceptions do not cross language boundaries... so you need to wrap your C++ functions with a function that catches all exceptions and reports a status code or does something acceptable other than invoking std::terminate.
The default terminate handler will call abort. If you don't want this behavior, define your own terminate handler and set it using set_terminate.

How to catch the null pointer exception? [duplicate]

This question already has answers here:
Catching access violation exceptions?
(8 answers)
Closed 6 years ago.
try {
int* p = 0;
*p = 1;
} catch (...) {
cout << "null pointer." << endl;
}
I tried to catch the exception like this but it doesn't work,any help?
There's no such thing as "null pointer exception" in C++. The only exceptions you can catch, is the exceptions explicitly thrown by throw expressions (plus, as Pavel noted, some standard C++ exceptions thrown intrinsically by standard operator new, dynamic_cast etc). There are no other exceptions in C++. Dereferencing null pointers, division by zero etc. does not generate exceptions in C++, it produces undefined behavior. If you want exceptions thrown in cases like that it is your own responsibility to manually detect these conditions and do throw explicitly. That's how it works in C++.
Whatever else you seem to be looking for has noting to do with C++ language, but rather a feature of particular implementation. In Visual C++, for example, system/hardware exceptions can be "converted" into C++ exceptions, but there's a price attached to this non-standard functionality, which is not normally worth paying.
You cannot. De-referencing a null-pointer is a system thing.
On Linux, the OS raises signals in your application. Take a look at csignal to see how to handle signals. To "catch" one, you'd hook a function in that will be called in the case of SIGSEGV. Here you could try to print some information before you gracefully terminate the program.
Windows uses structured-exception-handling. You could use the instristics __try/__except, as outlined in the previous link. The way I did it in a certain debug utility I wrote was with the function _set_se_translator (because it closely matches hooks). In Visual Studio, make sure you have SEH enabled. With that function, you can hook in a function to call when the system raises an exception in your application; in your case it would call it with EXCEPTION_ACCESS_VIOLATION. You can then throw an exception and have it propagate back out as if an exception was thrown in the first place.
There is a very easy way to catch any kind of exception (division by zero, access violation, etc.) in Visual Studio using try -> catch (...) blocks.
A minor project tweaking is enough. Just enable the /EHa option in project settings. See Project Properties -> C/C++ -> Code Generation -> Modify the Enable C++ Exceptions to "Yes With SEH Exceptions". That's it!
See details here:
http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
Dereferencing a null (or pointer that's past-the-end of array, or a random invalid pointer) results in undefined behavior. There's no portable way to "catch" that.
C++ doesn't do pointer checking (although I suppose some implementations could). If you try to write to a null pointer it is most likely going to crash hard. It will not throw an exception. If you want to catch this you need to check the value of the pointer yourself before you try to write to it.
Generally you can't. Even if you could it would be like trying to put a band aid on a submarine that has sprung a leak.
A crippled application can do far more damage than one that has crashed. My advice here would be to let it crash then fix why it crashed. Rinse. Repeat.
As others have said, you can't do this in C++.
If I can make a broader point: even in a language that allows you to catch it, the better action is to not touch null pointers. Catching an error when it's already blown up in your face, then deciding to just move on like it didn't happen, is not a good coding strategy. Things like null pointer dereference, stack overflow, etc., should be seen as catastrophic events and defensively avoided, even if your language allows you to react to it differently.
There is no platform independent way to do this. Under Windows/MSVC++ you can use __try/__except
But I wouldn't recommend doing it anyway. You almost certainly cannot recover correctly from a segmentation fault.
If you wanted to you could just do the pointer checking yourself and throw...
if (p == nullptr) throw std::exception("woot! a nullptr!")
p->foo();
so course this would only be to debug the problem, the nullptr should not occur in the first place :)
Short answer- you can't in a portable or standard way, because bugs like this are potentially corrupting the process itself.
Long answer- you can do more than you might think, and definitely more than the default of the program just crashing. However, you need to keep 3 things in mind:
1) These bugs are MORE severe than exceptions and often cannot present as exceptions to your logic.
2) Your detection and library handling of them WILL be platform-dependent on the back end, even though you can provide a clean abstract interface for public consumption.
3) There will always be some crashes that are so bad you cannot even detect them before the end.
Basically, faults like segfaults or heap corruption are not exceptions because they're corrupting the actual process running the program. Anything you coded into the program is part of the program, including exception handling, so anything beyond logging a nice error message before the process dies is inadvisable in the few cases it isn't impossible. In POSIX, the OS uses a signaling system to report faults like these, and you can register callback functions to log what the error was before you exit. In Windows, the OS can sometimes convert them into normal-looking exceptions which you can catch and recover from.
Ultimately, however, your best bet is to code defensively against such nightmares. On any given OS there will be some that are so bad that you cannot detect them, even in principle, before your process dies. For example, corrupting your own stack pointer is something that can crash you so badly that even your POSIX signal callbacks never see it.
In VC++ 2013 (and also earlier versions) you can put breakpoints on exceptions:
Press Ctrl + Alt + Delete (this will open the exception dialog).
Expand 'Win32 Exceptions'
Ensure that "0xC0000005 Access Violation" exception is checked.
Now debug again, a breakpoint will be hit exactly when the the null dereference happened.
There is no NULL pointer exception exist in c++ but still you want to catch the same then you need to provide your own class implementation for the same.
below is the example for the same.
class Exception {
public:
Exception(const string& msg,int val) : msg_(msg),e(val) {}
~Exception( ) {}
string getMessage( ) const {return(msg_);}
int what(){ return e;}
private:
string msg_;
int e;
};
Now based on NULL pointer check it can be threw like , throw(Exception("NullPointerException",NULL));
and below is the code for catching the same.
catch(Exception& e) {
cout << "Not a valid object: " << e.getMessage( )<< ": ";
cout<<"value="<<e.what()<< endl;
}

Wrapping C in C++, just for try/catch

So, I have a big piece of legacy software, coded in C. It's for an embedded system, so if something goes wrong, like divide by zero, null pointer dereference, etc, there's not much to do except reboot.
I was wondering if I could implement just main() as c++ and wrap it's contents in try/catch. That way, depending on the type of exception thrown, I could log some debug info just before reboot.
Hmm, since there are multiple processes I might have to wrap each one, not just main(), but I hope that you see what I mean...
Is it worthwhile to leave the existing C code (several 100 Klocs) untouched, except for wrapping it with try/catch?
Division by zero or null pointer dereferencing don't produce exceptions (using the C++ terminology). C doesn't even have a concept of exceptions. If you are on an UNIX-like system, you might want to install signal handlers (SIGFPE, SIGSEGV, etc.).
Since it's an embedded application it probably runs only on one platform.
If so its probably much simpler and less intrusive to install a proper interrupt handler / kernel trap handler for the division by zero and other hard exceptions.
In most cases this can be done with just a few lines of code. Check if the OS supports such installable exception handlers. If you're working on an OS-less system you can directly hook the CPU interrupts that are called during exceptions.
First of all, divide by zero or null pointer dereference won't throw exceptions. Fpe exceptions are implemented in the GNU C library with signals (SIGFPE). And are part of the C99 standard, not the C++ standard.
A few hints based in my experience in embedded C and C++ development. Depending on your embedded OS:
Unless you are absolutely sure of what you are doing, don't try/catch between threads . Only inside the same thread. Each thread usually has its own stack.
Throwing in the middle of legacy C code and catching, is going to lead to problems, since for example when you have jumped to the catch block out of the normal program flow, allocated memory may not be reclaimed, thus you have leaks which is far more problematic than divide by zero or null pointer dereference in an embedded system.
If you are going to use exceptions, throw them inside your C++ code with allocation of other "C" resources in constructors and deallocation in destructors.
Catch them just above the C++ layer.
I don't think machine code compiled from C does the same thing with regard to exceptions, as machine code compiled for C++ which "knows" about exceptions. That is, I don't think it's correct to expect to be able to catch "exceptions" from C code using C++ constructs. C doesn't throw exceptions, and there's nothing that guarantees that errors that happen when C code does something bad are caught by C++'s exception mechanism.
Divide by zero, null pointer dereference are not C or C++ exceptions they are hardware exceptions.
On Windows you can get hardware exceptions like these wrapped in a normal C++ exception if _set_se_translator() is used.
__try/__catch may also help. Look up __try/__catch, GetExceptionCode(), _set_se_translator() on MSDN, you may find what you need.
I think I remember researching on how to handle SIGSEGV ( usually generated when derefing invalid pointer, or dividing by 0 ) and the general advise I found on the net was: do nothing, let the program die. The explanation, I think a correct one, is that by the time you get to a SIGSEGV trap, the stack of the offending thread is trashed beyond repair.
Can someone comment if this is true?
Only work on msvc
__try
{
int p = 0;
p=p / 0;
}
__except (1)
{
printf("Division by 0 \n");
}