C++ standard: dereferencing NULL pointer to get a reference?
Solution 1
Dereferencing a NULL pointer is undefined behavior.
In fact the standard calls this exact situation out in a note (8.3.2/4 "References"):
Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior.
As an aside: The one time I'm aware of that a NULL pointer can be "dereferenced" in a well-defined way is as the operand to the sizeof
operator, because the operand to sizeof
isn't actually evaluated (so the dereference never actually occurs).
Solution 2
Dereferencing a NULL pointer is explicitly undefined behaviour in the C++ standard, so what you see is implementation specific.
Copying from 1.9.4 in the C++0x draft standard (similar to previous standards in this respect):
Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer). [Note: this International Standard imposes no requirements on the behavior of programs that contain undefined behavior. - end note]
Solution 3
Dereferencing a NULL pointer is undefined behaviour. You should check if a value is NULL before dereferencing it.
Solution 4
For completeness, this: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232 talks specifically about this issue.
shoosh
Working as a Software Engineer Millennium projects: https://github.com/shooshx CycleBlob, Lightcycle on a 3d surface using WebGL http://cycleblob.com
Updated on April 29, 2020Comments
-
shoosh about 4 years
I'm wondering about what the C++ standard says about code like this:
int* ptr = NULL; int& ref = *ptr; int* ptr2 = &ref;
In practice the result is that
ptr2
is NULL but I'm wondering, is this just an implementation detail or is this well defined in the standard?
Under different circumstances a dereferencing of a NULL pointer should result in a crash but here I'm dereferencing it to get a reference which is implemented by the compiler as a pointer so there's really no actual dereferencing of NULL. -
Johannes Schaub - litb about 14 yearsAnd indeed if it's an operand of
typeid
and if it's a null pointer of typePolymorphClass*
, then it's dereferenced and evaluated. Still it's well-defined (throwingbad_typeid
). I do really not like that specialtypeid
treatment. -
curiousguy over 12 yearsIt's funny, because nobody has been able to show where in the standard dereferencing a null pointer is explicitly made UB. The standard is incorrect here.
-
curiousguy over 12 yearsNonsense. unary
*
is actually the dereference operator. It actually performs the dereference operation. -
curiousguy over 12 yearsHum... very creative thinking. So, calling a member function with a null
this
is allowed!!! I wonder what they were smoking. Anyway, 7 years latter nothing has been done in the direction of this craziness. -
Gorpik over 12 years@curiousguy: 8.3.2.5 once again alludes to the fact that dereferencing a null pointer is undefined. But you are right, it does so as if it was explained elsewhere. Anyway, 1.3.13 explains that any behaviour that is not explicitly defined is considered undefined, so this can be the case.
-
curiousguy over 12 years"8.3.2.5" BTW, it's spelled 8.3.2/5. There is no 8.3.2.5 section. "any behaviour that is not explicitly defined is considered undefined" You are right: dereferencing a pointer is only defined if the pointer points to an object. But it would be slightly more clear if the standard was explicit about that - and less electronic ink would be spent on this non-issue.
-
valdo over 12 years@curiousguy: I advise you to compile this and see the code in the disassembler. The reference
ref
is essentially a pointer, so the above statement is just a pointer assignment behind the scenes. -
curiousguy over 12 yearsYou misunderstand me. I do not care what assembly code is generated. What is
*ptr
, according you? -
valdo over 12 years@curiousguy:
*ptr
is a dereferencing indeed. But this doesn't mean that it is actually done (evaluated). For instance, you can writesizeof(*ptr)
and the expression*ptr
is guaranteed not to be evaluated during run-time. -
curiousguy over 12 yearsIndeed, the operand of
sizeof
is not evaluated: you may writesizeof(1./0.)
without any problem. That's becausesizeof
is only concerned about the type of its operand. OTOH, the operand of&
is evaluated, otherwise what would address-of apply to? -
Kos over 11 yearsActually it isn't, according to stackoverflow.com/a/2474021/399317 (because of lvalue-to-rvalue conversion)
-
Adrian almost 11 yearsIt's unfortunate about not allowing a NULL reference. It exhibits some cool properties, but I guess it just complicates code. :( If preconditions were available and code could be better verified, NULL references could be used safely.
-
M.M over 9 yearsNotes are non-normative. This note was in fact removed as the result of DR 1102 with the stated reasoning being that it was not undefined behaviour to dereference a null pointer.
-
jforberg almost 9 yearssizeof() is an operator on the type of a variable, not the value. NULL pointers do have types.
-
Lightness Races in Orbit almost 9 years@jforberg: I don't see anyone here claiming otherwise?
-
jforberg almost 9 years@Lightness No-one is. I'm just clarifying.
-
supercat over 7 yearsInteresting that the #232 uses division by zero as an example of UB, when many C++ implementations implicitly incorporate IEEE-754, which defines the effects of division by positive and negative zero. Integer division by zero is UB, but the example doesn't specify that.
-
Jeremy over 7 yearsThat you have to use the word "many" is an example of UB.
-
Jack O'Connor about 4 yearsMy potentially flawed understanding: This is (probably in practice) not a dereference according to the output assembly, so you will not see a segfault or a valgrind error from this line alone. But it is a dereference according to the compiler's understanding of undefined behavior, so the compiler is allowed to output a totally broken program if it chooses to.