Disallow null references in safe code?

Jonathan M Davis jmdavisProg at gmx.com
Sat Feb 1 19:29:38 PST 2014


On Saturday, February 01, 2014 12:09:10 Andrei Alexandrescu wrote:
> On 2/1/14, 2:14 AM, Jonathan M Davis wrote:
> > On Saturday, February 01, 2014 04:01:50 deadalnix wrote:
> >> Dereferencing it is unsafe unless you put runtime check.
> > 
> > How is it unsafe? It will segfault and kill your program, not corrupt
> > memory. It can't even read any memory. It's a bug to dereference a null
> > pointer or reference, but it's not unsafe, because it can't access _any_
> > memory, let alone memory that it's not supposed to be accessing, which is
> > precisely what @safe is all about.
> 
> This has been discussed to death a number of times. A field access
> obj.field will use addressing with a constant offset. If that offset is
> larger than the lowest address allowed to the application, unsafety may
> occur.
> 
> The amount of low-address memory protected is OS-dependent. 4KB can
> virtually always be counted on. For fields placed beyond than that
> limit, a runtime test must be inserted. There are few enough 4KB objects
> out there to make this practically a non-issue. But the checks must be
> there.

Hmmm. I forgot about that. So, in essence, dereferencing null pointers is 
almost always perfectly safe but in rare, corner cases can be unsafe. At that 
point, we could either always insert runtime checks for pointers to such large 
types or we could mark all pointers of such types @system (that's not even 
vaguely acceptable in the general case, but it might be acceptable in a rare 
corner case like this). Or we could just disallow such types entirely, though 
it wouldn't surprise me if someone screamed over that. Runtime checks is 
probably the best solution, though with any of those solutions, I'd be a bit 
worried about there being bugs with the implementation, since we then end up 
with a rare, special case which is not well tested in real environments.

> >>   Which is stupid for something that can be verified at compile time.
> > 
> > In the general case, you can only catch it at compile time if you disallow
> > it completely, which is unnecessarily restrictive. Sure, some basic cases
> > can be caught, but unless the code where the pointer/reference is defined
> > is right next to the code where it's dereferenced, there's no way for the
> > compiler to have any clue whether it's null or not. And yes, there's
> > certainly code where it would make sense to use non-nullable references
> > or pointers, because there's no need for them to be nullable, and having
> > them be non-nullable avoids any risk of forgetting to initialize them,
> > but that doesn't mean that nullable pointers and references aren't useful
> > or that you can catch all instances of a null pointer or reference being
> > dereferenced at compile time.
> The Java community has a good experience with @Nullable:
> http://stackoverflow.com/questions/14076296/nullable-annotation-usage

Sure, and there are other things that the compiler can do to catch null 
dereferences (e.g. look at the first dereferencing of the pointer in the 
function that it's declared in and make sure that it was initialized or 
assigned a non-null value first), but the only way to catch all null 
dereferences at compile time would be to always know at compile time whether 
the pointer was null at the point that it's dereferenced, and that can't be 
done.

AFAIK, the only solution that guarantees that it catches all dereferences of 
null at compile time is a solution that disallows a pointer/reference from 
ever being null in the first place.

- Jonathan M Davis


More information about the Digitalmars-d mailing list