Daniel Keep wrote:

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.

Happens to me on some issues too, I don't ask for a workaround in the compiler, I just learn my lesson and never repeat that error.

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?

Easier to prove someone broke in when the window is shattered than if someone just went through the door, stole your stuff and left without any traces.

Why have laws when people could break them?

People break the law, some of them only for the challenge of it, some of them to survive, some just don't care. Remove the laws and you remove most of these behaviors you're trying to prohibit in the first place. Most of the time laws are there so corporate criminals can get rid of street criminals legally.

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

They keep most people out, or in. Hydrogen bombs are not something you expect the first guy on the street to own.

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

Because it also allows for countless different optimizations, at the price of also being able to shoot your own foot.

There, four similar questions and four completely different answers. My point is, there is no perfect all-around solution.

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

Why tell him to stop it? The guy will just kill himself at some point and raise the collective IQ of mankind in the process. Same for programming or anything else, if someone is dumb enough to repeat the same mistake over and over, he should find a new domain to work in.

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?

No, but you shouldn't rule out the fact that they may break, no matter what system you're working with.

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));
}

Also slower than a cast if the compiler doesn't use -inline. Debug builds are already painful enough as it is with realtime code.

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!

That's a case for variable initialization, not nullable/non-null types.

A nonnull type does not guarantee the value will *never* be null, even the simplest hack can get around it.

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.

There again, I favor stronger initialization semantics over nonnull types. This will get rid of most of these errors and still keep you on your toes when a segfault arise, if you only see a segfault once a year how will you know how to handle it :)

Most segfaults I have take me at most a few minutes to pinpoint. Its finding backdoors to compiler enforcements thats annoying.

Reply via email to