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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With