www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - flagging runtime null dereferencing

reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
I know this has been brought up many times, but I think possibly the 
usefulness of this feature has been underestimated, and its cost 
overestimated.

Consider several points:

1. check for null needs to be done only when the source of the variable is 
unknown.
2. segfaults can come from other sources, esp. memory corruption.  It is 
useful to distinguish null dereference (which is almost always an 'I forgot 
to initialize' error).
3. check for null can easily be removed during release mode, especially if 
it translates directly into an assert.
4. Yes, segfault is a loud error, but it's like hearing a gunshot from under 
water.  It's loud, but you have no idea where it's coming from, or whether a 
null dereference is to blame.  An assert is much more useful because it 
tells you the line of code that fails.  And please *please* don't tell me to 
create a core dump, or use Dr. Watson.  Not helpful.

I again propose that the D compiler in non-release mode inserts assert null 
checks where it can't prove that a pointer being dereferenced is not null, 
and removes those checks in release mode.

Example of "where it can't prove":
class C { void method();}
void fn(C c)
{
   c.method(); // can't prove c is not null, insert check
   c.method(); // know c is not null because it was checked above
}

In addition, I'd propose that the compiler does a static check to see if a 
null dereference definitely will happen.  e.g:

C c;
c.method(); // should be a compile error.

Ran into this again, and again, had to spend too much time finding it.

-Steve 
Nov 14 2008
next sibling parent Sean Kelly <sean invisibleduck.org> writes:
Steven Schveighoffer wrote:
 4. Yes, segfault is a loud error, but it's like hearing a gunshot from under 
 water.  It's loud, but you have no idea where it's coming from, or whether a 
 null dereference is to blame.  An assert is much more useful because it 
 tells you the line of code that fails.  And please *please* don't tell me to 
 create a core dump, or use Dr. Watson.  Not helpful.

I don't suppose it helps much, but on *nix you can set a signal handler to get the stack pointer, etc, and generate a stack trace from there. I'm pretty sure this is possible on Win32 as well, but it would likely have to be in the SEH code in the runtime. Sean
Nov 14 2008
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:gfkui3$228r$1 digitalmars.com...
 In addition, I'd propose that the compiler does a static check to see if a 
 null dereference definitely will happen.  e.g:

 C c;
 c.method(); // should be a compile error.

 Ran into this again, and again, had to spend too much time finding it.

I would love to see this happen. Unfortunately, I'm guessing it would fall under the same category as getting a compile-time error on a missing return, that category being "Compile-time checks Walter doesn't want to implement because getting it flagged in *all* cases would require really fancy flow-control analysis".
Nov 14 2008
prev sibling next sibling parent reply Chad J <gamerchad __spam.is.bad__gmail.com> writes:
Steven Schveighoffer wrote:
 I know this has been brought up many times, but I think possibly the 
 usefulness of this feature has been underestimated, and its cost 
 overestimated.
 
 Consider several points:
 
 1. check for null needs to be done only when the source of the variable is 
 unknown.
 2. segfaults can come from other sources, esp. memory corruption.  It is 
 useful to distinguish null dereference (which is almost always an 'I forgot 
 to initialize' error).
 3. check for null can easily be removed during release mode, especially if 
 it translates directly into an assert.
 4. Yes, segfault is a loud error, but it's like hearing a gunshot from under 
 water.  It's loud, but you have no idea where it's coming from, or whether a 
 null dereference is to blame.  An assert is much more useful because it 
 tells you the line of code that fails.  And please *please* don't tell me to 
 create a core dump, or use Dr. Watson.  Not helpful.
 
 I again propose that the D compiler in non-release mode inserts assert null 
 checks where it can't prove that a pointer being dereferenced is not null, 
 and removes those checks in release mode.
 
 Example of "where it can't prove":
 class C { void method();}
 void fn(C c)
 {
    c.method(); // can't prove c is not null, insert check
    c.method(); // know c is not null because it was checked above
 }
 
 In addition, I'd propose that the compiler does a static check to see if a 
 null dereference definitely will happen.  e.g:
 
 C c;
 c.method(); // should be a compile error.
 
 Ran into this again, and again, had to spend too much time finding it.
 
 -Steve 
 
 

Hell, just the naive version of inserting assert( c !is null, ... ); before dereferences would be extremely awesome. I've already spent too much of my life on this crap.
Nov 14 2008
parent Robert Fraser <fraserofthenight gmail.com> writes:
Chad J wrote:
 Hell, just the naive version of inserting assert( c !is null, ... ); 
 before dereferences would be extremely awesome.  I've already spent too 
 much of my life on this crap.

Yup, yup; agreed. Thankfully, Windows raises a structured exception for an AV, and using the Team0xf backtrace hack, it works just as good as a NPE raised in Java/C#.
Nov 14 2008
prev sibling parent "Stewart Gordon" <smjg_1998 yahoo.com> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:gfkui3$228r$1 digitalmars.com...
I know this has been brought up many times, but I think possibly the 
usefulness of this feature has been underestimated, and its cost 
overestimated.

I agree. <snip>
 3. check for null can easily be removed during release mode, especially if 
 it translates directly into an assert.

NullDerefError (or whatever we end up calling it) should probably be a separate exception class, just like the existing ArrayBoundsError and SwitchError. These are all things that are omitted when compiling in release mode. Stewart. -- My e-mail address is valid but not my primary mailbox. Please keep replies on the 'group where everybody may benefit.
Nov 15 2008