Suppose we get some data as a sequence of bytes and want to rethink this sequence as a structure (having some guarantees that the data is really in the correct format). For example:
#include <fstream> #include <vector> #include <cstdint> #include <cstdlib> #include <iostream> struct Data { std::int32_t someDword[629835]; std::uint16_t someWord[9845]; std::int8_t someSignedByte; }; Data* magic_reinterpret(void* raw) { return reinterpret_cast<Data*>(raw); // BAD! Breaks strict aliasing rules! } std::vector<char> getDataBytes() { std::ifstream file("file.bin",std::ios_base::binary); if(!file) std::abort(); std::vector<char> rawData(sizeof(Data)); file.read(rawData.data(),sizeof(Data)); if(!file) std::abort(); return rawData; } int main() { auto rawData=getDataBytes(); Data* data=magic_reinterpret(rawData.data()); std::cout << "someWord[346]=" << data->someWord[346] << "\n"; data->someDword[390875]=23235; std::cout << "someDword=" << data->someDword << "\n"; }
Now magic_reinterpret is really bad here because it violates strict alias rules and therefore calls UB.
How to do this instead of not calling UB, and not making any copies of the data, for example, using memcpy ?
EDIT : The above getDataBytes() function was actually considered as some kind of immutable function. The real example is ptrace(2) , which on Linux, when request==PTRACE_GETREGSET and addr==NT_PRSTATUS , writes (on x86-64) one of two possible structures of different sizes, depending on the width of the trace, and returns the size. Here ptrace calling code cannot predict what type of structure it will receive until it actually calls the call. How can you then safely rethink the results that it gets as the correct type of pointer?
c ++ undefined-behavior struct strict-aliasing
Ruslan
source share