C++ Logo

std-discussion

Advanced search

Placement new into static storage violates strict pointer safety?

From: Andrew Schepler <aschepler_at_[hidden]>
Date: Fri, 23 Aug 2019 18:49:02 -0400
By a strict reading of the Standard (any version since C++11), it
seems like when an implementation has strict pointer safety, there is
no correct way of using placement new with memory that is not from
::operator new(size_t). For an example, it seems this program would
have undefined behavior:

#include <new>
#include <type_traits>
#include <iostream>

std::aligned_storage<sizeof(int), alignof(int)>::type storage;

int main() {
    int* p = new(&storage) int(1);
    std::cout << *p;
}

Although it occupies memory with static duration, the int object has
dynamic storage duration by [expr.new] "Entities created by a
new-expression have dynamic storage duration." Nothing in [basic.stc]
contradicts that, and that makes sense, since storage duration is
mainly about the object's lifetime, not its memory.

Safely-derived pointer values and integer representations of
safely-derived pointers are defined in [basic.stc.dynamic.safety]/2-3.
The only way to get a value in one of those two categories without
using another such value is that a pointer value is safely-derived if
it is "the value returned by a call to the C++ standard library
implementation of ::operator new(std::size_t);". There is no such
call in this program, so there are no safely-derived pointer values.

But then the strict pointer requirement sentence in
[basic.stc.dynamic.safety]/4 is that "an implementation may have
strict pointer safety, in which case a pointer value referring to an
object with dynamic storage duration that is not a safely-derived
pointer value is an invalid pointer value unless the referenced
complete object has previously been declared reachable." So the value
of p, even though it points at an int object, is an invalid pointer
value, even during the lifetime of that int object.

A footnote for that same sentence claims "This section [or subclause]
does not impose restrictions on indirection through pointers to memory
not allocated by ::operator new." This probably reflects the intent,
but doesn't seem match the normative text.

Should I submit a Defect Report? Maybe paragraph 4 should say
something like "... a pointer value which refers to an object
occupying bytes within a block of memory allocated by the C++ standard
library implementation of ::operator new(std::size_t); and is not a
safely-derived pointer value ... reachable. [Note: Any such object was
created by a new-expression and has dynamic storage duration. - end
note]"

-- Andrew Schepler

Received on 2019-08-23 17:51:17