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

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;
}
}

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.

I have played with throwing exceptions out of signal handlers and
it's not going to work in a reliable way at all, on Linux at least.
The compiler doesn't generate exception handling frames for blocks
of code it doesn't expect to throw an exception, and it doesn't
expect single instructions to do so. AFAIK this is true for both
dmd and gdc. When you throw an exception and the stack unwinding
procedure doesn't find an EH frame, it will abort your application.
gcc has two switches to remedy this: -fnon-call-exceptions that
expects exceptions to be thrown from dereferences and arithmetics;
and -fasynchronous-unwind-tables that generates EH frames
encompassing all instructions. Alas gdc doesn't support these.
I've played with this a bit in my own stacktracing module
(which you can find at http://zygfryd.net/jive/).
The same disclaimer applies.
PS. Throwing exceptions across C code aborts too, you can however
add one of the previously mentioned flags when compiling C code.

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.

I have played with throwing exceptions out of signal handlers and
it's not going to work in a reliable way at all, on Linux at least.
The compiler doesn't generate exception handling frames for blocks
of code it doesn't expect to throw an exception, and it doesn't
expect single instructions to do so. AFAIK this is true for both
dmd and gdc. When you throw an exception and the stack unwinding
procedure doesn't find an EH frame, it will abort your application.
gcc has two switches to remedy this: -fnon-call-exceptions that
expects exceptions to be thrown from dereferences and arithmetics;
and -fasynchronous-unwind-tables that generates EH frames
encompassing all instructions. Alas gdc doesn't support these.
I've played with this a bit in my own stacktracing module
(which you can find at http://zygfryd.net/jive/).
The same disclaimer applies.
PS. Throwing exceptions across C code aborts too, you can however
add one of the previously mentioned flags when compiling C code.

I haven't had much need for this stuff yet -- I do mostly
metaprogramming stuff -- but thanks for the link. Whenever I do
applications work, I'll use your stuff.

I have played with throwing exceptions out of signal handlers and
it's not going to work in a reliable way at all, on Linux at least.
The compiler doesn't generate exception handling frames for blocks
of code it doesn't expect to throw an exception, and it doesn't
expect single instructions to do so.

I uses this approach and it works just fine. (DMD/Linux and IIRC DMD/Win)

PS. Throwing exceptions across C code aborts too, you can however
add one of the previously mentioned flags when compiling C code.

I've never seen this.
OTOH I don't actually catch the exception as the only thing I actually
uses the exception for is a poor man's stack trace:
// add this at the top of all functions.
scope(failure) writef(">>"__FILE__":"~itoa!(__LINE__)~\n);

I uses this approach and it works just fine. (DMD/Linux and IIRC DMD/Win)

My bad, I must have remembered wrong, it does indeed work fine
with dmd/linux; there aren't even any calls to abort in deh2.d
So the problem only applies to gdc, for which the runtime uses
gcc's unwind procedure from libgcc_s.

PS. Throwing exceptions across C code aborts too, you can however
add one of the previously mentioned flags when compiling C code.

Just a small correction: you need -fexceptions or -funwind-tables,
-fnon-call-exceptions and -fasynchronous-unwind-tables aren't necessary
unless you're throwing out of signal handlers.
(Applies to gcc)

I've played with this a bit in my own stacktracing module
(which you can find at http://zygfryd.net/jive/).
The same disclaimer applies.

Your project looks interesting. I'd be especially interested in seeing some
usage examples.
I'll be extremely interested when the disclaimers for stacktrace are lessened.
Specifically, linux-only and "doesn't work very well for either DMD or GDC".
If they were gone, I'd be using this library tonight!

I've played with this a bit in my own stacktracing module
(which you can find at http://zygfryd.net/jive/).
The same disclaimer applies.

Your project looks interesting. I'd be especially interested in seeing
some usage examples.
I'll be extremely interested when the disclaimers for stacktrace are
lessened. Specifically, linux-only and "doesn't work very well for either
DMD or GDC". If they were gone, I'd be using this library tonight!

Well you're obviously using Tango; Tango's had traced exceptions for a
while, just get flectioned and link it in when you compile your project.

I've played with this a bit in my own stacktracing module
(which you can find at http://zygfryd.net/jive/).
The same disclaimer applies.

Your project looks interesting. I'd be especially interested in seeing
some usage examples.
I'll be extremely interested when the disclaimers for stacktrace are
lessened. Specifically, linux-only and "doesn't work very well for
either
DMD or GDC". If they were gone, I'd be using this library tonight!

Well you're obviously using Tango; Tango's had traced exceptions for a
while, just get flectioned and link it in when you compile your project.

Stupid question - what functionality will that get me? A full backtrace is
only part of it. The other (bigger?) part is a way to capture seg faults
reliably on all platforms. My project runs on windows, linux, mac, 32-bit,
and 64-bit. I have yet to find a reliable way...

I've played with this a bit in my own stacktracing module
(which you can find at http://zygfryd.net/jive/).
The same disclaimer applies.

some usage examples.
I'll be extremely interested when the disclaimers for stacktrace are
lessened. Specifically, linux-only and "doesn't work very well for
either
DMD or GDC". If they were gone, I'd be using this library tonight!

while, just get flectioned and link it in when you compile your project.

Stupid question - what functionality will that get me? A full backtrace is
only part of it. The other (bigger?) part is a way to capture seg faults
reliably on all platforms. My project runs on windows, linux, mac, 32-bit,
and 64-bit. I have yet to find a reliable way...

Flectioned gives segfault tracing on Linux. If a Windows-compatible way
could be found, it might not be too hard to hack in.

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.

Why would this be slow? seg-v are caused by hardware. When a seg-v is
noticed it triggers an interrupt and the OS goes from there. Until you
get a seg-v there should be NO cost at all.
Am I missing something?

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.

Why would this be slow? seg-v are caused by hardware. When a seg-v is
noticed it triggers an interrupt and the OS goes from there. Until you
get a seg-v there should be NO cost at all.
Am I missing something?

Handling an error will be slower. Handling a lack of an error will be
faster.

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.

Why would this be slow? seg-v are caused by hardware. When a seg-v is
noticed it triggers an interrupt and the OS goes from there. Until you
get a seg-v there should be NO cost at all.
Am I missing something?

Handling an error will be slower. Handling a lack of an error will be
faster.

"Exceptions are a slow way to handle a seg-v's after it happens"
Ok that makes a difference. I missed that because 1) I generally assume
that performance after an errors is not an issue and 2) in general my
programs respond to a seg-v by quitting (with an uncaught exception) on
the assumption that their is nothing else it can safely do.
I'd be interested in which of theses assumptions is erroneous in your
case and why.

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.

Why would this be slow? seg-v are caused by hardware. When a seg-v is
noticed it triggers an interrupt and the OS goes from there. Until
you get a seg-v there should be NO cost at all.
Am I missing something?

Handling an error will be slower. Handling a lack of an error will be
faster.

"Exceptions are a slow way to handle a seg-v's after it happens"
Ok that makes a difference. I missed that because 1) I generally assume
that performance after an errors is not an issue and 2) in general my
programs respond to a seg-v by quitting (with an uncaught exception) on
the assumption that their is nothing else it can safely do.
I'd be interested in which of theses assumptions is erroneous in your
case and why.

I was speaking about the case where you're using exceptions as flow
control rather than a means of error handling. So if you're just going
to catch the segfault exception, log it, and quit, fine; performance
doesn't matter. If you're going to do something else if you get a
segfault and it isn't an error, that will be slower. Not to mention
you'd get pwned in code review.

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

I just did a test C++ app in Windows (MsDev) ..
and I do catch exceptions thrown by a null ptr reference.
Which is what I was expecting to happen in D.
Of course I can check for a NULL ptr ...
but catching exceptions is for error handling too !!
bugs happen ;-)
One point I forgot to mention that might be important (??) :
the D code is called by C(++) code
(I'm using FLTK2 gui toolkit, calling D code on events)
I'll do some tests to see if I the same thing happens under 'normal'
situations...
thx

I just did a test C++ app in Windows (MsDev) ..
and I do catch exceptions thrown by a null ptr reference.
Which is what I was expecting to happen in D.

Segfaults in Windows pass through the Structured Exception Handling
mechanism, as do many other hardware-level errors. It's the Windows
response to signals in Unix. And DMD is nice enough to turn these into
D exceptions for you. It sounds like GDC does its exception handling
another way however, and does not.
Sean

I just did a test C++ app in Windows (MsDev) .. and I do catch
exceptions thrown by a null ptr reference.
Which is what I was expecting to happen in D.

Segfaults in Windows pass through the Structured Exception Handling
mechanism, as do many other hardware-level errors. It's the Windows
response to signals in Unix. And DMD is nice enough to turn these into
D exceptions for you. It sounds like GDC does its exception handling
another way however, and does not.
Sean

I just did a test C++ app in Windows (MsDev) .. and I do catch
exceptions thrown by a null ptr reference.
Which is what I was expecting to happen in D.

Segfaults in Windows pass through the Structured Exception Handling
mechanism, as do many other hardware-level errors. It's the Windows
response to signals in Unix. And DMD is nice enough to turn these
into D exceptions for you. It sounds like GDC does its exception
handling another way however, and does not.

Any way to get Flectioned tracing them?

Generating a stack trace within a signal handler would probably work,
though it isn't guaranteed to. I'd say it depends on how the OS handles
hardware signals. Throwing exceptions from signal handlers has the same
problem.
Sean

ok, it seems this is a Windows vs 'Unix' difference...
actually, more like a "Windows type" compiler vs GNU / 'Unix' compiler !
a simple C++ app that tries to write to a NULL ptr :
On Windows :
- compiled w. MsDev6 : the 'exception' is "catch"ed
- compiled w. mingw32 C++ : seg faults
(same w. cygwin)
So depending on the compiler, the behaviour is different.
AND .. same difference between GDC & DMD !!
(as Jarrett mentionned)
the same code (Windows again) ..
+ compiled w. gdc does not catch the 'exception', (segfault)
+ compiled w. dmd DOES catch the error
niiiice .. NOT ;-)
I'll have to look into this signal stuff .. time to read those other posts
again !
thank you
Phil