dereferencing null

Chad J chadjoan at __spam.is.bad__gmail.com
Sun Mar 4 23:50:25 PST 2012


On 03/05/2012 01:25 AM, Walter Bright wrote:
> On 3/4/2012 6:31 PM, Chad J wrote:
>> class Bar
>> {
>> int foo;
>> }
>>
>> void main()
>> {
>> Bar bar;
>> try {
>> bar.foo = 5;
>> } catch ( Exception e ) {
>> writefln("%s",e);
>> }
>> }
>>
>> DMD 2.057 on Gentoo Linux, compiled with "-g -debug". It prints this:
>> Segmentation fault
>>
>> Very frustrating!
>
> This is what I get (I added in an import std.stdio;):
>
> dmd foo -gc
> gdb foo
> GNU gdb (GDB) 7.2-ubuntu
> Copyright (C) 2010 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "x86_64-linux-gnu".
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>...
> Reading symbols from /home/walter/cbx/mars/foo...done.
> (gdb) run
> Starting program: /home/walter/cbx/mars/foo
> [Thread debugging using libthread_db enabled]
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x0000000000401e45 in D main () at foo.d:13
> 13 bar.foo = 5;
> (gdb) bt
> #0 0x0000000000401e45 in D main () at foo.d:13
> #1 0x000000000040aa9b in rt.dmain2.main() ()
> #2 0x0000000000636010 in ?? ()
> #3 0x00007ffff7fdeae0 in ?? ()
> #4 0x00007fffffffeb30 in ?? ()
> #5 0x00007fffffffea00 in ?? ()
> #6 0x000000000040a41b in rt.dmain2.main() ()
> #7 0x0000000000000001 in ?? ()
> #8 0x0000000000000019 in ?? ()
> #9 0x0000000000636020 in ?? ()
> #10 0x00007fffffffeb30 in ?? ()
> #11 0x00007ffff7ffe4c0 in ?? ()
> #12 0x00007fffffffe8b0 in ?? ()
> #13 0x00007fffffffeb30 in ?? ()
> #14 0x00007fffffffea30 in ?? ()
> #15 0x000000000040aaee in rt.dmain2.main() ()
> #16 0x000000000040aa84 in rt.dmain2.main() ()
> #17 0x00007fffffffeb30 in ?? ()
> #18 0x00007fffffffea80 in ?? ()
> #19 0x000000000040a41b in rt.dmain2.main() ()
> #20 0x0000000000000001 in ?? ()
> #21 0x0000000000000019 in ?? ()
> #22 0x0000000000636020 in ?? ()
> #23 0x0000000000000001 in ?? ()
> #24 0x0000000000636020 in ?? ()
> #25 0x00007fffffffee01 in ?? ()
> #26 0x00007fffffffeb30 in ?? ()
> #27 0x00007fffffffeb30 in ?? ()
> #28 0x000000000040a3b3 in main ()
> (gdb)
>
> By running it under gdb (the debugger), it tells me what file and line
> it failed on, and gives a lovely stack trace.
>
> There really are only 3 gdb commands you need (and the only ones I
> remember):
>
> run (run your program)
> bt (print a backtrace)
> quit (exit gdb)
>
> Voila!
>
> Also, a null pointer exception is only one of a whole menagerie of
> possible hardware-detected errors. There's a limit on the compiler
> instrumenting code to detect these. At some point, it really is worth
> learning how to use the debugger.

Problems:
- I have to rerun the program in a debugger to see the stack trace. 
This is a slow workflow.  It's a big improvement if the segfault is hard 
to find, but only a small improvement if the segfault is easy to find. 
Very bad if I'm prototyping experimental code and I have a bunch to go 
through.
- It only gives one line number.  I imagine there's a way to get it to 
spill the rest?  At least it's the most important line number. 
Nonetheless, I commonly encounter cases where the real action is 
happening a few levels into the stack, which means I want to see ALL the 
line numbers /at one time/.
- As I mentioned in another post, it is unreasonable to expect others to 
run your programs in a debugger.  I like it when my users can send me 
stacktraces.  (And they need to have ALL the line numbers displayed with 
no extra coercion.)  There are a number of occasions where I don't even 
need to ask how to reproduce the bug, because I can just tell by looking 
at the trace.  Super useful!
- It doesn't seem to be possible to catch() these hardware errors.  Booooo.


I wouldn't even expect ALL hardware errors to be instrumented in the 
compiler.  At least get the common ones.  Null dereference is remarkably 
common.  I can't actually think of others I care about right now.  Array 
boundary errors and assertions already seem to have their own exceptions 
now; they were great pests back in the day when this was not so.  The 
error messages could use a lot of work though.  (Range Violation should 
print the index used and the index boundaries, and simpler assertions 
such as equality should print the values of their operands.)

I'm pretty sure other languages like C# and Java get this right. 
Haven't used those two in a while though.  Haxe... totally got this 
right.  Also Actionscript 3 by proxy.  Hell, even Synergy/DE, the DIBOL 
(!!) derivative that I use at work, /gets this right/.  I get 
stacktraces for null dereferences in these languages.  It's /really/ 
convenient and useful.  I consider D to be very backwards in this regard.


More information about the Digitalmars-d mailing list