Share via


Why can't NullReferenceException tell you the type of the instance that was null?

If you have done much managed development you have run into a NullReferenceException more times that you’d care to count. The CLR throws this exception when you try to access instance state on null instance…

One of your internal customers suggested we give the type of instance that was null to help track down the errors. Not a bad idea, but Chris Brumme made it clear this is harder than you might expect…

The NullReferenceException occurs because an instruction like “call [eax+44]” or “mov edx, [esi+24]” has resulted in an access violation. We don’t retain nearly enough information to form a correspondence between a particular register being NULL at a particular EIP and the fact that a particular reference in the application was null. Especially since the EIP might be in a shared helper like a write barrier routine or an array helper. In those cases, we would have to perform a limited stack walk to get the effective EIP.

The machinery that would be required to improve this error message is huge. For the foreseeable future, you will have to rely on debuggers, or on FX code explicitly checking and throwing an appropriate NullArgumentException.

Oh well, back to the debugger!

But this does raise a number of interesting questions….

1) I said that we throw a NullReferenceException when you try to access instance “state” (eg a field). What if you have an instance method that does not touch any instance state (for example an instance method that just does a Console.WriteLine (“hello“)). Will you get a NullReferenceException when you call that? Why? Hint: It is one of those interesting differences between the CLR and the C# programming language.

2) As Chris implies above, the .NET Framework and WinFX generally do argument checking on all publicly exposed APIs. I continue to think this is a good thing to help you track to errors, but we do pay a very small perf price for these… Are they worth it?

3) Back in the day we had a number of long debates about the naming of NullReferenceException. As you VB folks know, there is no such this as Null in the VB world (expect maybe in the database)… VB uses the term “Nothing” for this concept. In retrospect should we have called in “NullReferenceOrNothingException”? Has anyone worked with a VB developer that was actually confused by this?

 

rewritting history here a little bit... I put “Empty” instead of “Nothing” when I first posted. Thanks to those of you who pointed it out.

Comments

  • Anonymous
    February 22, 2004
    Hi Brad,

    I don't advocate the "NullReferenceOrEmptyException" approach myself.
    Otherwise, you'd have to extend the name for .NET COBOL developers etc., wouldn't you?

    I think one, well-understood term should be used. The term "null" is the best one, in the general case, if you ask me. The fact that is also a keyword in some languages is a happy coincidence.

    Martin
    Incidentally, the equivalent of "null" in VB is "Nothing".
  • Anonymous
    February 22, 2004
    Null isn't a completely foreign reference to most VB devs, I would think. For one thing, if you've ever called a Win32 or other C function from VB, you've probably encountered vbNullString. And any VB dev who has SQL experience should have encountered NULL in that context as well.

    And for those relatively (I hope) VB devs who have never used Win32, SQL, or learned any C-like language, picking up Null as an idiom for Nothing should be pretty easy anyway.
  • Anonymous
    February 22, 2004
    relatively few. Need more coffee...
  • Anonymous
    February 23, 2004
    I can't seem to get trackbacks working between DasBlog and .Text, I must be doing something wrong here. Anyway: I have an idea as to why it should be possible to call methods on null objects from the CLR point of view, but why it fails in C#:

    http://jelledruyts.homeip.net/PermaLink.aspx?guid=92a28981-949c-450c-b3d0-d40a4bf6277d

    Regarding the "NullReferenceOrEmptyException"-idea: please no. That just sounds awful, NullReferenceException is perfectly acceptable to me. The term "null" is and has been used for years to indicate a special place in memory, or a non-existant object, or a database row that has no data. "Emtpy" to me sounds like an existing object without any state (which could make sense sometimes).
  • Anonymous
    February 23, 2004
    Has anyone worked with a VB developer that was actually confused by this? I've worked with VB developers that get confused about LOTS of things... Never specifically this though :)
  • Anonymous
    February 23, 2004
    The comment has been removed
  • Anonymous
    February 23, 2004
    No, as a VB developer, I don't think the error message should have been called "...NullOrEmpty...". But then I'm one of those developers who thinks that the VB6 -> VB.Net 'Cleanup' didn't go far enough. I hate seeing, "...static, or shared in VB.Net..." in the documentation. As the saying goes, "It's the framework, stupid!" The closer my programming language resembles the framework, the less of a mind shift I have to go through when I'm switching between the two.
  • Anonymous
    February 23, 2004
    The comment has been removed
  • Anonymous
    February 23, 2004
    VB calls null "Nothing" (not Empty - that was what an uninitialised Variant was called), so if anything a VB-er would expect a "NothingReferenceException"
  • Anonymous
    February 23, 2004
    As far as #2 goes, PLEASE continue to do as much argument checking as possible. One of the most frustrating things about Win32 is that it lets you make mistakes that you don't find out about until something else possibly even unrelated goes wrong. Further, if you don't check all arguments, developers won't catch bugs and your hands will be tied (relatively anyway) when making new versions of the API. Better to catch everything immediately. And not just in a 'debug' mode either, because one thing you find is that some developers are criminally incompetent and wouldn't use a debug mode if their program ran fine in release but had errors in debug. Don't allow their kind to sneak by.
  • Anonymous
    February 23, 2004
    'A very small perf. price' That's another thing. It's clear there isn't a performance need by that statement. Don't introduce chaos for a 5% speed-up. Moore's Law will get you that in short order anyway, so it's needless, but development time will definitely be slowed by more than that trying to figure out what on earth is going on..
  • Anonymous
    February 23, 2004
    Brad
  • Anonymous
    February 23, 2004
    You run into this exception more than you care to count? You have got to be kidding Brad, maybe VB programmers do but anybody who ever worked with C/C++ knows to check their object references (pointers) before they use them. But CLR's design guidelines actually make people use objects without checking if they have them, we've talked about this before (returning empty strings/arrays/collections versus returning nulls). And this is why I think that rule is just going to lead to worse code and you're going to have to think about things like this.
  • Anonymous
    February 23, 2004
    >Has anyone worked with a VB developer that was actually confused by this?
    Never found one, many VB devs use both C# and VB so never found any problem with nullreference exception (indeed many warning and/or compiler messages reflects C# logic...).
  • Anonymous
    February 23, 2004
    >> VB uses the term “Empty” for this concept.

    Actually, it uses Nothing. Empty is something quite different.
  • Anonymous
    February 23, 2004
    How does the CLR decide if a given AV should be converted to a NullReferenceException or not? Does it check that the referenced address was in fact 0? Does it look at the faulting instruction/address?

    I hope it does at least check the referenced address. I'd hate to debug a process where an AV resulting from memory corruption was converted to a managed exception and silently handled.
  • Anonymous
    February 23, 2004
    Update: with a little help from Brad (and Don), I think I found the answer to his pop quiz :-)

    http://jelledruyts.homeip.net/PermaLink.aspx?guid=92a28981-949c-450c-b3d0-d40a4bf6277d
  • Anonymous
    February 24, 2004
  1. yes.

    3) NullReferenceOrNothingException: unnecessary complexity.

    Please keep the naming conventions and design guidelines as simple as possible. Otherwise, they will be ignored, and your efforts are in vain.