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