dereferencing null

Chad J chadjoan at __spam.is.bad__gmail.com
Wed Mar 7 21:45:28 PST 2012


On 03/07/2012 11:17 PM, Jonathan M Davis wrote:
> On Wednesday, March 07, 2012 22:58:44 Chad J wrote:
>> On 03/07/2012 10:40 PM, Jonathan M Davis wrote:
>>> On Wednesday, March 07, 2012 22:36:50 Chad J wrote:
>>>> On 03/07/2012 10:08 PM, Jonathan M Davis wrote:
>>>>> On Wednesday, March 07, 2012 20:44:59 Chad J wrote:
>>>>>> On 03/07/2012 10:21 AM, Steven Schveighoffer wrote:
>>>>>>> You can use sentinels other than null.
>>>>>>>
>>>>>>> -Steve
>>>>>>
>>>>>> Example?
>>>>>
>>>>> Create an instance of the class which is immutable and represents an
>>>>> invalid value. You could check whether something is that value with the
>>>>> is operator, since there's only one of it. You could even make it a
>>>>> derived class and have all of its functions throw a particular exception
>>>>> if someone tries to call them.
>>>>>
>>>>> - Jonathan M Davis
>>>>
>>>> Makes sense.  Awfully labor-intensive though.  Doesn't work well on
>>>>
>>>> classes that can't be easily altered.  That is, it violates this:
>>>>> - Do not modify the implementation of UnreliableResource.  It's not
>>>>> always
>>>>> possible.
>>>>
>>>> But, maybe it can be turned it into a template and made to work for
>>>> arrays too...
>>>
>>> Personally, I'd probably just use null. But if you want a sentinel other
>>> than null, it's quite feasible.
>>>
>>> - Jonathan M Davis
>>
>> Wait, so you'd use null and then have the program unconditionally crash
>> whenever you (inevitably) mess up sentinel logic?
>
> Yes. Proper testing will find most such problems. And it's not like having a
> non-null sentinel is going to prevent you from having problems. It just means
> that you're not distinguishing between a variable that you forgot to
> initialize and one which you set to the sentinel value. Your program can die
> from a variable being null in either case. And in _both_ cases, it's generally
> unsafe to continue executing your program anyway.
>

The important difference in using explicit sentinel values here is that 
they are not null, and thus very unlikely to have been caused by memory 
corruption.  It allows us to distinguish between the two sources of 
empty variables.

With a better way to do sentinel values, I can isolate my cleaner 
looking code from the scarier looking code that comes from any number of 
places.

I also am not too worried about null values that come from stuff that 
was simply forgotten, instead of intentionally nulled.  I DO tend to 
catch those really early in testing, and they are unlikely to happen to 
begin with due to the close association between declaration and 
initialization.

> And honestly, in my experience, null pointers are a very rare thing. You catch
> them through solid testing.
>
> - Jonathan M Davis


Sorry, your testing doesn't help me as well as you probably wish it 
does.  Our experiences must be very different.  I run into a lot of 
cases where things can't be tested automatically, or at least not 
easily.  Think along the lines of graphics operations, interactively 
driven code (ex: event lifetimes), network code, etc.  Testing can help 
things between endpoints, but it doesn't help much where the rubber 
meets the road.

And that's just game dev.  Then I go to work at my job, the one that 
makes money, and experience code from the 80s.  Rewriting it is 
completely impractical for near-term projects (though a complete 
phase-out of crufty old crap is on the horizon one way or another!). 
Yes it has bugs.  If I had an attitude of "crash on every little nit" 
then these things wouldn't last a few seconds (OK, exaggeration).  So I 
recover as well as possible, and occasionally rewrite strategically 
important pieces.  But the world is NOT perfect, so relying on it being 
perfect is %100 unhelpful to me.  Also, "quit your job" is not an 
acceptable solution. ;)  Now, in principle, we will never have to deal 
with D code like that.  Nonetheless, these experiences do make me 
severely afraid of lacking the tools that keep me safe.

And then there are still those occasional weird problems where sentinel 
values are needed, and its so stateful that there's a vanishingly 
close-to-zero chance that testing will catch the stuff that it needs to.
So I test it as well as I can and leave a "if all else fails, DO THIS" 
next to the dubious code.  Indiscriminate segfaulting deprives me of 
this last-ditch option.  There is no longer even a way to crash 
elegantly.  It all just goes to hell.

Long story short: in practice, I find that recovering from sentinel 
dereference is not only VERY safe, but also orders of magnitude less 
frustrating for both my users and me.

(Memory corruption, on the other hand, is something I am very unfamiliar 
with, and sort of afraid of.  So I'm willing to ditch nulls.)


More information about the Digitalmars-d mailing list