templatetypedef
templatetypedef

Reputation: 372724

Is it undefined behavior in C++ to dereference an invalid pointer but not use the result?

Consider the following piece of C++ code:

int main() {
    int* ptr; // Deliberately uninitialized
    (void) *ptr;     // Dereference, do not use result
}

Does this code result in undefined behavior? I assume that the answer is "yes" even though the value of *ptr is not actually used anywhere. Is there a particular part of the spec that guarantees this?

(I apologize if this is a duplicate, but I can't seem to find anything else on the site that specifically asks this question.)

Upvotes: 2

Views: 1013

Answers (4)

Marinos K
Marinos K

Reputation: 1819

According to the standard, dereferencing a non-initialised pointer is undefined behaviour. However, in real life this is rarely the case: compilers are clever enough to remove code like this since it's not actually used anywhere.. So even if dereferencing the pointer is undefined behaviour, if you don't use the result the chances are that you don't actually dereference it. I tested your code with clang++ and NO CODE has been generated.

from the standard (4.1):

An lvalue (3.10) of a non-function, non-array type T can be converted to an rvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the lvalue refers is not an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program that necessitates this conversion has undefined behavior. If T is a non-class type, the type of the rvalue is the cv-unqualified version of T. Otherwise, the type of the rvalue is T.

Upvotes: -1

Galik
Galik

Reputation: 48605

Simply dereferencing a pointer that has not been allocated or is marked as read-only can cause a hardware exception in the CPUs memory management unit. So even if you don't use whatever garbage value would be returned by dereferencing a pointer that contains a random value, there is no guarantee the CPU would return from such an event.

However, according to the ISO C++11 Standard a pointer that is declared uninitialized must have a singular value. So the value of an uninitialized pointer is not undefined as in it is not garbage.

However the Standard states that most operations on such a singular value pointer are undefined with the exception of overwriting the singular value with a non singular value:

24.2.1 In general [ iterator.requirements.general ]

5 [ Example: After the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer. — end example ] Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that satisfy the DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move operation. [ Note: This guarantee is not offered for default initialization, although the distinction only matters for types with trivial default constructors such as pointers or aggregates holding pointers. — end note ] In these cases the singular value is overwritten the same way as any other value. Dereferenceable values are always non-singular.

Upvotes: 8

callyalater
callyalater

Reputation: 3102

It is not undefined behavior according to the Standard.

Here is the official discussion and explanation from the open-std review page.

We agreed that the approach in the standard seems okay: p = 0; *p; is not inherently an error. An lvalue-to-rvalue conversion would give it undefined behavior.

Additionally in the standard [Section 4.10.2], it says:

A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a non-null pointer value of a pointer to object type to a “pointer to cv void” represents the address of the same byte in memory as the original pointer value. The null pointer value is converted to the null pointer value of the destination type.

Upvotes: -2

Weak to Enuma Elish
Weak to Enuma Elish

Reputation: 4637

You're reading the value of an uninitialized variable (the pointer). That is undefined behavior.

Interestingly, because *ptr is a discarded value expression, it isn't going to undergo lvalue to rvalue conversion. So if *ptr was uninitialized, it would be safe.

Upvotes: 1

Related Questions