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

Reply via email to