un-catched segfault exception

Christopher Wright dhasenan at gmail.com
Wed Jan 9 17:31:49 PST 2008


philippe quesnel wrote:
> I have a bug that causes a segmentation fault (null object)...
> but try/catch fails to catch it !! ??
> 
> even with
>  catch (Exception e)
>    ...
>  catch (Error e)
>    ...
>  catch // "last catch"
>    ...
> 
> I still cant catch the exception & the app crashes.
> 
> I'm on Windows (XP), with
> gdc.exe (GCC) 3.4.5 (mingw special) (gdc 0.24, using dmd 1.020).
> 
> I must be missing some important point here .. this cant be the normal behaviour !!??
> 
> any help / suggestions would be appreciated.
> thank you
> Philippe

This certainly can be normal behavior -- C++ does it this way, after 
all. A segfault is not an exception or an error; it's a signal. You can 
trap the segfault with a signal handler but you can't catch it in a 
try/catch block.

With exceptions, your program essentially contains a try/catch block 
around all your code that terminates your program if you didn't handle 
the exception. That's probably not correct, but it's close enough for my 
purposes at the moment.

With signals, the operating system essentially registers a signal 
handler; when it gets signal, it determines which application is 
responsible. If that application has a signal handler, that handler is 
called; otherwise, your program is toast.

What you can do, though, is convert a signal to an exception. It's going 
to be a lot slower than just checking a pointer to see if it's null, but 
if you have traced exceptions, the debugging benefit is enormous. 
Someone else probably has a cleaner version, but here's something that I 
cooked up a couple weeks back. Tested on Linux, dmd1.023-ish; not 
guaranteed to work for you. It might destroy your computer, kill your 
firstborn, raise Cthulhu from the depths, overwrite your doctoral thesis 
with dancing hamsters, et cetera.

The whole point of this code is getting a stack trace rather than an 
opaque segfault message (if you're using Tango, just inherit from 
TracedException rather than Exception and reference Flectioned by Thomas 
Kuehne). It is unreasonable to use anything like this as a regular means 
of flow control, due to performance reasons and the hideousness of using 
exceptions for flow control aside from error handling.

/** Public domain.
     Traps SIGSEGV and throws an exception, so you should get a stack trace
     when you segfault.
   */
class NullReferenceException : Exception {
     this (char[] msg) {
         super(msg);
     }

     this () {
         super ("tried to dereference a pointer to a nonexistent memory 
region");
     }
}

const int SA_SIGINFO = 4;
const int SIGSEGV = 11;

extern(C) {
     struct sig_action {
         // Dunno if a function* would work here...
         void* action;
         int flags;
         void* restorer;
     }

     int sigaction (int signal, sig_action* action, sig_action* oact);
}

void segv_throw (int i) {
     throw new NullReferenceException();
}

static this () {
     sig_action act;
     act.action = &segv_throw;
     act.flags = SA_SIGINFO;
     sigaction(SIGSEGV, &act, null);
}


debug (SegvTest) {
     void main () {
         uint* p = null;
         uint k = *p;
     }
}



More information about the Digitalmars-d mailing list