Null references redux

Daniel Keep daniel.keep.lists at gmail.com
Sat Sep 26 20:51:58 PDT 2009



Jeremie Pelletier wrote:
> ...
> 
> This is something for the runtime or the debugger to deal with. My
> runtime converts access violations on windows or segfaults on linux into
> exception objects, which unwind all the way down to main where it
> catches into the unhandled exception handler (or crash handler) and I
> get a neat popup with a "hello, your program crashed at this point, here
> is a backtrace with resolved symbols and filenames along with current
> registers and loaded modules, would you like a cup of coffee while you
> solve the problem?". I sent that crash handler to D.announce last week too.

See my long explanation that NPEs are only symptoms; very rarely do they
put up a big sign saying "what ho; the problem is RIGHT HERE!"

> The compiler won't be able to enforce *every* nonnull reference and
> segfaults are bound to happen, especially with casting. While it may
> prevent most of them, any good programmer would too, I don't remember
> the last time I had a segfault on a null reference actually.

I do.  It took a day and a half to track it back to the source.

> I can see what the point is with nonnull references, but I can also see
> its not a bulletproof solution. ie "Object foo = cast(Object)null;"
> would easily bypass the nonnull enforcement, resulting in a segfault the
> system is trying to avoid.

Why lock the door when someone could break the window?

Why have laws when people could break them?

Why build a wall when someone could park a hydrogen bomb next to it?

Why have a typesystem when you could use casting to put the float
representation of 3.14159 into a void* and then dereference it?

Casting is not an argument against non-null references because casting
can BREAK ANYTHING.

"Doctor, it hurts when I hammer nails into my shin."

"So stop doing it."

> What about function parameters, a lot of parameters are optional
> references, which are tested and then used into functions whose
> parameters aren't optional. It would result in a lot of casts, something
> that could easily confuse people and easily generate segfaults.

So what you're saying is: better to never, ever do error checking and
just start fixing things after they've broken?

And why is everything solved via casting?  Look: here's a solution
that's less typing than a cast, AND it's safe.  You could even put
nonnull it in object.d!

T notnull(U : T?, T)(U obj)
{
    if( obj is null ) throw new NullException;
    return cast(T) obj;
}

void foo(Quxx o)
{
    o.doStuff;
}

void foo(Quxx? o)
{
    foo(notnull(o));
}

> Alls I'm saying is, nonnull references would just take the issue from
> one place to another.

YES.

THAT'S THE POINT.

It would take the error from a likely unrelated location in the
program's execution and put it RIGHT where the mistake initially occurs!

> Like Walter said, you can put a gas mask to ignore
> the room full of toxic gas, but that doesn't solve the gas problem in
> itself, you're just denyinng it exists. Then someday you forget about
> it, remove the mask, and suffocate.
> 
> Jeremie

That's what NPEs are!  They're a *symptom* of you passing crap in to
fields or functions.  They very, VERY rarely actually point out what the
underlying mistake is.



More information about the Digitalmars-d mailing list