7

In short, is the following code considered to have undefined behavior?

int main()
{
    int *p = <some invalid pointer value>;
}

For a compiling example, take the following code:

int main()
{
    int *p = new int;
    delete p; // Now p has an invalid pointer value.
    int *q = p; // UB?
}

I've done some research on the topic, so these are the relevant information I've found so far:

A pointer value (according to cppreference) can be one of:

  • A pointer to an object or function;
  • A pointer past the end of an object;
  • The null pointer value;
  • An invalid pointer value.

Also, according to cppreference,

Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.

This thread addresses some uses of invalid pointers. Specifically, this answer mentions the Rationale document (C99), which has the following paragraph (section 6.3.2.3):

Regardless how an invalid pointer is created, any use of it yields undefined behavior. Even assignment, comparison with a null pointer constant, or comparison with itself, might on some systems result in an exception.

I'm not sure what's the state of affairs for C++, but I'd consider that, given the answers on the linked thread, uses of invalid pointers result in undefined behavior. Note, though, that assignment is not the same as initialization, so I'm not sure initialization is considered a use.

18
  • 2
    @super "As long as you don't try to dereference it all is ok." This is wrong. See the quotes from the standard provided by OP. Commented May 26, 2018 at 20:16
  • 1
    Not looking for the language standards, but loading a pointer into a 68000 address register or an x86 segment register would validate the address. If it is not currently mapped to RAM, it would trap. Commented May 26, 2018 at 20:31
  • 1
    That only proves implementation-defined. And BTW one would expect the implementation to not load into those registers if the pointer is never dereferenced. Commented May 26, 2018 at 20:41
  • 1
    @rustyx - Just pointing to reasons why copying an invalid pointer is not well defined. The guys writing the language standards were well aware of this. And if I had ever written a compiler for the 68000, I would surely have used the dedicated address registers for copying pointers. Why waste a data register for that? Commented May 26, 2018 at 21:47
  • 1
    @BoPersson The 68000 only checks the validity of the value stored in an address register when you try to dereference it. These registers are only 'special' in the sense that they can be used in indirect instructions whereas data registers cannot. And while you are correct that loading a segment register with an invalid value will cause an exception in x86, the compiler will only emit code to load such a register when it is going to dereference the pointer. This operation is expensive so the compiler won't do it unless it has to. Commented May 27, 2018 at 5:11

1 Answer 1

4

You’ve all but answered this yourself: it’s implementation defined, not undefined, in C++. The standard says just what you quoted (which I found by consulting the appropriate index). It doesn’t matter whether it’s initialization: the lvalue-to-rvalue conversion on the pointer object explicitly constitutes a use.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.