View mode: basic / threaded / horizontal-split · Log in · Help
March 05, 2012
Re: dereferencing null
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.
March 05, 2012
Re: dereferencing null
On Sunday, March 04, 2012 21:31:21 Chad J wrote:
> On 03/03/2012 02:06 PM, Walter Bright wrote:
> > On 3/3/2012 2:13 AM, bearophile wrote:
> >> Walter:
> >>> Adding in software checks for null pointers will dramatically slow
> >>> things
> >>> down.
> >> 
> >> Define this use of "dramatically" in a more quantitative and objective
> >> way,
> >> please. Is Java "dramatically" slower than C++/D here?
> > 
> > You can try it for yourself. Take some OOP code of yours, and insert a
> > null check in front of every dereference of the class handle.
> 
> I have a hard time buying this as a valid reason to avoid inserting such
> checks.  I do think they should be optional, but they should be
> available, if not default, with optimizations for signal handlers and
> such taken in the cases where they apply.
> 
> Even if it slows my code down 4x, it'll be a huge win for me to avoid
> this stuff.  Because you know what pisses me off a helluva lot more than
> slightly slower code?  Spending hours trying to figure out what made my
> program say "Segmentation fault".  That's what.

Really? I rarely run into segfaults, and when I do, it's easy enough to enable 
core dumps, rerun the program, and then get an actual stack trace (along with 
the whole state of the program for that matter). Yes, upon occasion, it would 
be useful - especially if you're talking about a large program where you can't 
simply rerun it with core dumps enabled and quickly reproduce the problem, but 
in my experience, the reality of the matter is that it's a very rare 
occurence. And if it really is something that keeps causing you problems, on 
Linux at least, it's very easy to enable a signal handler to get you a stack 
trace.

So, I can see your complaint, but I find that it's rarely justified in practice.

- Jonathan M Davis
March 05, 2012
Re: dereferencing null
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.
March 05, 2012
Re: dereferencing null
On 2012-03-05 07:25, 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.

Is demangling supposed to work on Mac OS X?

-- 
/Jacob Carlborg
March 05, 2012
Re: dereferencing null
On Monday, 5 March 2012 at 09:09:30 UTC, Jacob Carlborg wrote:
> On 2012-03-05 07:25, Walter Bright wrote:
>> […]
>> run (run your program)
>> bt (print a backtrace)
>> quit (exit gdb)
>> […]
> Is demangling supposed to work on Mac OS X?

As the D demangling support was added in GDB 7.<something>, 
unfortunately no, as Apple ships an ancient (customized) version.

David
March 05, 2012
Re: dereferencing null
On Monday, 5 March 2012 at 00:33:18 UTC, Nathan M. Swan wrote:
> On Saturday, 3 March 2012 at 02:51:41 UTC, Walter Bright wrote:
>> Adding in software checks for null pointers will dramatically 
>> slow things down.
>
> What about the debug/release difference? Isn't the point of 
> debug mode to allow checks such as assert, RangeError, etc? 
> "Segmentation fault: 11" prevents memory from corrupting, but 
> it isn't helpful in locating a bug.

It can in linux. Enable debug symbols, and core dumps, open in gdb

$ ulimit -c unlimited
$ dmd files.d -gc
$ gdb ./files core
March 05, 2012
Re: dereferencing null
On 3/4/2012 11:50 PM, Chad J wrote:
> 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.

I don't get this at all. I find it trivial to run the program with a debugger:

  gdb foo
  >run

that's it.

> - 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/.

That's because the runtime library is compiled without debug symbols in it. If 
it was compiled with -g, the line numbers would be there. You of course can 
compile the library that way if you want. Debug symbols substantially increase 
your program size.


> - 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!

I agree that customers emailing you a stack trace is a reasonable point. Andrei 
also brought up the point of the problems with using a debugger on a remote 
server machine.


> 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.

No hardware support for them, so no choice.


> 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.)

The added bloat for this would be substantial.


> 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.

Notably, C and C++ do not do what you suggest.
March 05, 2012
Re: dereferencing null
>
> No hardware support for them, so no choice.
>

I am just going to leave this here...

*Fast Bounds Checking Using Debug Register*

http://www.ecsl.cs.sunysb.edu/tr/TR225.pdf
March 05, 2012
Re: dereferencing null
Le 03/03/2012 21:10, Timon Gehr a écrit :
> On 03/03/2012 09:00 PM, deadalnix wrote:
>> Le 03/03/2012 20:06, Walter Bright a écrit :
>>> On 3/3/2012 2:13 AM, bearophile wrote:
>>>> Walter:
>>>>
>>>>> Adding in software checks for null pointers will dramatically slow
>>>>> things
>>>>> down.
>>>>
>>>> Define this use of "dramatically" in a more quantitative and objective
>>>> way,
>>>> please. Is Java "dramatically" slower than C++/D here?
>>>
>>> You can try it for yourself. Take some OOP code of yours, and insert a
>>> null check in front of every dereference of the class handle.
>>
>> Why would you want to check every time ? You program will get a signal
>> from the system if it try to deference a null pointer, so thing can be
>> done in the signal handler, and no cost is involved.
>
> The signal will likely be the same for the following two code snippets:
>
> void main(){
> Object o;
> o.toString();
> }
>
> void main(){
> *cast(int*)0xDEADBEEF = 1337;
> }
>
>
> How to detect whether or not the access violation was actually caused by
> a null pointer?

Signal hanlder are provided a - system dependant - structure that 
contains such informations.

This is used to detect stackoverflow as well a null pointer deference. 
Lib like libsigsegv can help a lot to implement such a thing.
March 05, 2012
Re: dereferencing null
On 2012-03-05 11:38, Walter Bright wrote:
> On 3/4/2012 11:50 PM, Chad J wrote:
>> 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.
>
> Notably, C and C++ do not do what you suggest.

Just because C and C++ do something in a certain way doesn't make it a 
valid reason to do the same thing in D.

I think this is an argument we need to stop using immediately. It just 
shows we're stuck in our ways, can't innovate and can't think for our self.

-- 
/Jacob Carlborg
2 3 4 5 6 7 8 9 10
Top | Discussion index | About this forum | D home