www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How D intercepts runtime errors

reply Serg Kovrov <user domain.invalid> writes:
I am quite exited by how D handling runtime errors. For example bad
pointer dereferencing.

Consider simple C/C++ example (I used try catch blocks just to
illustrate an idea):
 #include <stdio.h>
 int main(int argc, char *argv[])
 {
 	char h[] = "hello";
 	char *p = h;
 	p = (char*)123; // me evil hax0r
 	try
 	{
 		printf("pointer is %d\n", p);
 		printf("value is %s\n", p);
 	}
 	catch (...)
 	{
 		printf("gotcha!");
 	}
 	return 0;
 }
Sure it chases. And here is equivalent code in D:
 import std.stdio;
 int main(char[][] args)
 {
 	char[] h = "hello";
 	char[]* p = &h;
 	p = cast(char[]*)0x123; // me evil hax0r
 	try
 	{
 		writefln("pointer is %d", p);
 		writefln("value is %s", *p);
 	}
 	catch (Exception e)
 	{
 		writef("gotcha!");
 	}
 	return 0;
 }
Which (to my admiration) somehow works =) And I'm wondering how it works. I'm more or less understand what happen in C/C++ when incorrect pointer being dereferenced. But could someone kindly explain to me how it works in D, please? I mean, who (and how) is checking pointer I try to use, who throws exception, etc.. I is it garbage collector routine injected into my executable, or some other part of standard library, or maybe something completely different... And of course, how it could affect performance. Ah, there is some more. Is there something D could not intercept? I mean is there a way to crash/segfault program? Kinda silly question, yes. But knowing that could help to avoid it. Thanks.
Jul 27 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Serg Kovrov" <user domain.invalid> wrote in message 
news:eaagfg$1k5d$1 digitaldaemon.com...

 I'm more or less understand what happen in C/C++ when incorrect pointer
 being dereferenced. But could someone kindly explain to me how it works
 in D, please?

 I mean, who (and how) is checking pointer I try to use, who throws
 exception, etc.. I is it garbage collector routine injected into my
 executable, or some other part of standard library, or maybe something
 completely different...
D, as well as most modern C++ implementations, use the underlying OS's exception handling mechanisms; on Windows, it's Structured Exception Handling (SEH), and on *nix, it's usually signals. I'm just going to discuss SEH, as I don't know much about *nix signals, but I'd assume they are fairly similar. What happens is that the application registers an exception handler with the SEH system. When a system exception occurs (such as a memory access violation, which is, by the way, detected by the processor and memory controller - it's in the hardware), the OS calls the exception handler, giving it a chance to convert the system exception into a software exception which the program can understand. You can see this in /dmd/src/phobos/internal/deh.c, in the _d_translate_se_to_d_exception function: notice the "cast STATUS_ACCESS_VIOLATION" clause.
 And of course, how it could affect performance.
All exception handling methods incur some performance penalty, but since access violations are implemented in the PC hardware, there is no performance penalty that you can't circumvent.
 Ah, there is some more. Is there something D could not intercept? I mean
 is there a way to crash/segfault program? Kinda silly question, yes. But
 knowing that could help to avoid it.
Perhaps if there is an exception thrown before the exception handler routine is registered? Another possibility is if an exception is thrown outside the _Dmain's try block (see /dmd/src/phobos/internal/dmain2.d). Maybe an out of memory exception or something.
Jul 27 2006
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:eaak8g$1o0k$1 digitaldaemon.com...

 All exception handling methods incur some performance penalty, but since 
 access violations are implemented in the PC hardware, there is no 
 performance penalty that you can't circumvent.
I meant to say "since access violations are implemented in the PC hardware, there is a very slight performance penalty, but one which all programs experience (the OS included) regardless of whether or not they're using exception handling."
Jul 27 2006
parent Sean Kelly <sean f4.ca> writes:
Jarrett Billingsley wrote:
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:eaak8g$1o0k$1 digitaldaemon.com...
 
 All exception handling methods incur some performance penalty, but since 
 access violations are implemented in the PC hardware, there is no 
 performance penalty that you can't circumvent.
I meant to say "since access violations are implemented in the PC hardware, there is a very slight performance penalty, but one which all programs experience (the OS included) regardless of whether or not they're using exception handling."
It's uncommon (though not unheard of) for an application to intentionally dereference an invalid pointer, so the performance hit isn't a huge issue. Stack unwinding as the exception propagates is what takes most of the time anyway. Sean
Jul 27 2006
prev sibling parent reply Serg Kovrov <user domain.invalid> writes:
Thanks for reply, Jarrett. It is exactly what I wondering about.

* Jarrett Billingsley:
 D, as well as most modern C++ implementations, use the underlying OS's 
 exception handling mechanisms; on Windows, it's Structured Exception 
 Handling (SEH), and on *nix, it's usually signals.  I'm just going to 
 discuss SEH, as I don't know much about *nix signals, but I'd assume they 
 are fairly similar.
Yes, I see microsoft c++ compiler has nonstandard keywords to support SEH - __try and __except. But i do not have one right now to try it out. In mingw/GCC's c++ compiler, on the other hand, there is no support (yet, I hope) for it. Need to say I haven't tried other c++ compilers, but GDC do not support it either. And this is really sad. Is it D language feature, or Digital Mars D compiler? Is such functionality part of a language standard or standard library? It would be nice if on all compiler implementations one could expect same behavior.
Jul 28 2006
parent Sean Kelly <sean f4.ca> writes:
Serg Kovrov wrote:
 Thanks for reply, Jarrett. It is exactly what I wondering about.
 
 * Jarrett Billingsley:
 D, as well as most modern C++ implementations, use the underlying OS's 
 exception handling mechanisms; on Windows, it's Structured Exception 
 Handling (SEH), and on *nix, it's usually signals.  I'm just going to 
 discuss SEH, as I don't know much about *nix signals, but I'd assume 
 they are fairly similar.
Yes, I see microsoft c++ compiler has nonstandard keywords to support SEH - __try and __except. But i do not have one right now to try it out. In mingw/GCC's c++ compiler, on the other hand, there is no support (yet, I hope) for it. Need to say I haven't tried other c++ compilers, but GDC do not support it either. And this is really sad. Is it D language feature, or Digital Mars D compiler? Is such functionality part of a language standard or standard library? It would be nice if on all compiler implementations one could expect same behavior.
I think it would be useful to eventually standardize, as it would make throwing exceptions across dynamic library boundaries and such much more likely to work portably. And I think it eventually will be. Check the bottom of the ABI: http://www.digitalmars.com/d/abi.html For what it's worth, DMC and DMD-Win32 both use SEH for exception handing. If you want to look at DMD's code for this, check phobos/internal/deh.c Sean
Jul 28 2006