Использование std:: write для "проверки" значения указателя "указатель на объект" с С++ 17
В соответствии с этим answer, поскольку С++ 17, даже если указатель имеет правильный адрес и разыменовывает правильный тип, это может вызвать поведение undefined.
alignas(int) unsigned char buffer[2*sizeof(int)];
auto p1=new(buffer) int{};
auto p2=new(p1+1) int{};
*(p1+1)=10; // UB since c++17
Причина в том, что значение указателя p1+1
равно указатель за концом объекта. Может ли этот пример вернуться к определенному поведению с помощью std::launder
:
*std::launder(p1+1)=10; // still UB?
Во-вторых, будет ли это полезно и в следующем случае?
alignas(int) unsigned char buffer[3*sizeof(int)];
auto pi = new (buffer) int{};
auto pc = reinterpret_cast<unsigned char*>(pi);//not a "pointer to" an element of buffer
//since buffer[0] and *pc
//are not pointer interconvertible
//pc+2*sizeof(int) would be UB
auto pc_valid = std::launder(pc) //pc_valid is a pointer to an element of buffer
auto pc_valid2 = pc_valid+2*sizeof(int); //not UB thanks to std::launder
auto pi2 = new (pc_valid2) int{};
Ответы
Ответ 1
Нет. Байты, составляющие объект int
object p2
, указывают на то, что достижимый через p1+1
.
Правило "достижимое" в основном означает, что launder
не позволяет вам получить доступ к хранилищу, к которому вы не можете получить юридический доступ через исходный указатель. Поскольку непрозрачная функция может launder
указывать столько, сколько она хочет, разрешая этот вид махинаций, существенно подавляет анализ эвакуации.