I could not find a lot of resources like this that cover all of the edge cases of the strict aliasing rule. If I understand correctly, in C++ it is UB to access an object that does not exist at a particular location (for example cast of uint32_t* to float* and access is illegal since there is no float object alive at that address), and the only way to start a lifespan of such an object is using placement new and a simple assignment does not suffice. This brings me to my question:
// CASE 1
uint64_t arr[8] = {}; //dynamic type of each element now uint64_t?
for(int ii = 0; ii < 8; ++ii){
new (arr+ii) double(3.14); // dynamic type now double?
}
arr[0] = 10; // dereference as uint64_t while
//dynamic type is double? so this violates strict aliasing I assume?
// CASE 2
uint64_t* arr = new uint64_t[8]; //dynamic type of each element now uint64_t?
// CASE 3
uint64_t* mal_arr = (uint64_t*)malloc(8*sizeof(uint64_t)); // dynamic type now void?
mal_arr[0] = 10; // if it is indeed void, this must be illegal, correct?
Case 1:
Firstly, I'll assume that alignof(double) >= alignof(uint64_t)
. Otherwise the very first placement-new is UB.
Next, from what I can tell, arr+ii
on the second iteration is UB, because +
can only move a pointer between elements of the same array, and the lifetime of the array ends once you placement-new the first double
on top of it. But this is mostly a theoretical issue, +
should work correctly in practice.
Then arr[0] = 10;
is an outright strict aliasing violation, causing UB.
Case 3:
This used to be UB (placement-new is missing), but C++20 gave us implicit-lifetime types, which can be created implicitly by malloc
and some other methods.