C++ standard: dereferencing NULL pointer to get a reference?

40,513

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.

Share:
40,513
shoosh
Author by

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, 2020

Comments

  • shoosh
    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
    Johannes Schaub - litb about 14 years
    And indeed if it's an operand of typeid and if it's a null pointer of type PolymorphClass*, then it's dereferenced and evaluated. Still it's well-defined (throwing bad_typeid). I do really not like that special typeid treatment.
  • curiousguy
    curiousguy over 12 years
    It'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
    curiousguy over 12 years
    Nonsense. unary * is actually the dereference operator. It actually performs the dereference operation.
  • curiousguy
    curiousguy over 12 years
    Hum... 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
    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
    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
    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
    curiousguy over 12 years
    You misunderstand me. I do not care what assembly code is generated. What is *ptr, according you?
  • valdo
    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 write sizeof(*ptr) and the expression *ptr is guaranteed not to be evaluated during run-time.
  • curiousguy
    curiousguy over 12 years
    Indeed, the operand of sizeof is not evaluated: you may write sizeof(1./0.) without any problem. That's because sizeof is only concerned about the type of its operand. OTOH, the operand of & is evaluated, otherwise what would address-of apply to?
  • Kos
    Kos over 11 years
    Actually it isn't, according to stackoverflow.com/a/2474021/399317 (because of lvalue-to-rvalue conversion)
  • Adrian
    Adrian almost 11 years
    It'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
    M.M over 9 years
    Notes 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
    jforberg almost 9 years
    sizeof() is an operator on the type of a variable, not the value. NULL pointers do have types.
  • Lightness Races in Orbit
    Lightness Races in Orbit almost 9 years
    @jforberg: I don't see anyone here claiming otherwise?
  • jforberg
    jforberg almost 9 years
    @Lightness No-one is. I'm just clarifying.
  • supercat
    supercat over 7 years
    Interesting 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
    Jeremy over 7 years
    That you have to use the word "many" is an example of UB.
  • Jack O'Connor
    Jack O'Connor about 4 years
    My 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.