Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dereference null is not always UB?

I've always known for a fact that the Standard mandates dereferencing null is UB. However,

(Link 1) says

p = 0; *p; is not inherently an error.

and provides a link to

(Link 2) says

*p is not an error when p is null unless the lvalue is converted to an lvalue

(I believe it's a typo and probably should read lvalue is converted to an rvalue)

Link 1 also says

char* p = 0; char *q = &*(p)

is "not undefined", which I could only read as well-defined or at least implementation-defined

Can a language lawyer provide an authoritative explanation of what's going on?

like image 813
PoweredByRice Avatar asked Apr 21 '17 03:04

PoweredByRice


People also ask

What happens when you dereference null?

Dereferencing a null pointer always results in undefined behavior and can cause crashes. If the compiler finds a pointer dereference, it treats that pointer as nonnull. As a result, the optimizer may remove null equality checks for dereferenced pointers.

What is dereferencing null?

A NULL pointer dereference occurs when the application dereferences a pointer that it expects to be valid, but is NULL, typically causing a crash or exit. Extended Description. NULL pointer dereference issues can occur through a number of flaws, including race conditions, and simple programming omissions.

How do I stop null pointer dereference in C++?

There are a few ways to avoid null pointer dereferences. One is to use a language that does not allow them, such as Java. Another is to always check pointers for NULL before dereferencing them.

What happens if you dereference an uninitialized pointer?

For an uninitialized function pointer that has a non-zero value, the dereference can cause an exception to occur. This happens if the storage that the uninitialized pointer points to is read-protected. Usually, comparing uninitialized function pointers results in undefined behavior.


1 Answers

I explored the topic of indirection through null pointers in this answer. In short, it is indeed well-defined per se, just as elaborated in your cited Core issues. The committee used the notion of an empty lvalue as proposed many years ago (but never adopted); *p is supposed to be such an empty lvalue, and unless we attempt to access the (non-existent) memory location behind that lvalue (for example, by performing an lvalue-to-rvalue conversion), all other operations behave as expected. E.g. &*p is equivalent to p, unless p is invalid. (This also works for pointers past-the-end of an array, which is necessary for the common idiom &arr[n]).

I also started drafting a paper for empty lvalues (this is WIP, and the rebase against N4640 isn't complete yet), so there's a chance we'll see more of this at a later stage.

like image 151
Columbo Avatar answered Oct 17 '22 23:10

Columbo