Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Contrary to popular opinion, it is possible to have a reference that is NULL.</p> <pre><code>int * p = NULL; int &amp; r = *p; r = 1; // crash! (if you're lucky) </code></pre> <p>Granted, it is much harder to do with a reference - but if you manage it, you'll tear your hair out trying to find it. References are <em>not</em> inherently safe in C++!</p> <p>Technically this is an <strong>invalid reference</strong>, not a null reference. C++ doesn't support null references as a concept as you might find in other languages. There are other kinds of invalid references as well. <em>Any</em> invalid reference raises the spectre of <strong>undefined behavior</strong>, just as using an invalid pointer would.</p> <p>The actual error is in the dereferencing of the NULL pointer, prior to the assignment to a reference. But I'm not aware of any compilers that will generate any errors on that condition - the error propagates to a point further along in the code. That's what makes this problem so insidious. Most of the time, if you dereference a NULL pointer, you crash right at that spot and it doesn't take much debugging to figure it out.</p> <p>My example above is short and contrived. Here's a more real-world example.</p> <pre><code>class MyClass { ... virtual void DoSomething(int,int,int,int,int); }; void Foo(const MyClass &amp; bar) { ... bar.DoSomething(i1,i2,i3,i4,i5); // crash occurs here due to memory access violation - obvious why? } MyClass * GetInstance() { if (somecondition) return NULL; ... } MyClass * p = GetInstance(); Foo(*p); </code></pre> <p>I want to reiterate that the only way to get a null reference is through malformed code, and once you have it you're getting undefined behavior. It <strong>never</strong> makes sense to check for a null reference; for example you can try <code>if(&amp;bar==NULL)...</code> but the compiler might optimize the statement out of existence! A valid reference can never be NULL so from the compiler's view the comparison is always false, and it is free to eliminate the <code>if</code> clause as dead code - this is the essence of undefined behavior.</p> <p>The proper way to stay out of trouble is to avoid dereferencing a NULL pointer to create a reference. Here's an automated way to accomplish this.</p> <pre><code>template&lt;typename T&gt; T&amp; deref(T* p) { if (p == NULL) throw std::invalid_argument(std::string("NULL reference")); return *p; } MyClass * p = GetInstance(); Foo(deref(p)); </code></pre> <p>For an older look at this problem from someone with better writing skills, see <a href="http://www.gotw.ca/conv/002.htm" rel="noreferrer">Null References</a> from Jim Hyslop and Herb Sutter.</p> <p>For another example of the dangers of dereferencing a null pointer see <a href="https://blogs.msdn.microsoft.com/oldnewthing/20171222-00/?p=97635" rel="noreferrer">Exposing undefined behavior when trying to port code to another platform</a> by Raymond Chen.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload