Dado o código
struct A {};
auto obj = new A;
std::vector<unsigned char> buffer;
buffer.resize(sizeof(obj));
std::memcpy(buffer.data(), &obj, sizeof(obj)); // this copies the pointer, not the object!
// ...
auto ptr = *reinterpret_cast<A**>(buffer.data()); // is this UB?
delete ptr;
é o uso de reinterpret_cast
, neste caso, UB? Eu diria que sim, porque memcpy
não inicia o tempo de vida de uma instância, violando a regra estrita de alias (por isso std::bit_cast
foi adicionada ao C ++ 20).
E se eu substituir o elenco por outro memcpy
(para ler o ponteiro) o programa estaria bem definido?
c++
language-lawyer
Timo
fonte
fonte
buffer.data()
que supostamente contém um ponteiro paraA
, e nãobuffer.data()
ele mesmo que é um ponteiro paraA
.std::vector
? (Presumo suas garantias são quaisquer que sejam suas garantias alocador.)A*
objeto no buffer. O padrão diz sobre a função alocador padrão :: alocar: "Retorna: um ponteiro para o elemento inicial de uma matriz de armazenamento de tamanhon * sizeof(T)
, alinhado adequadamente para objetos do tipo T ".Respostas:
Sim, este código tem um comportamento indefinido. Não há nenhum objeto do tipo
A*
no local apontado porbuffer.data()
. Tudo o que você fez foi copiar a representação do objeto desse ponteiro no seu vetor [basic.types] / 4 . Como os ponteiros são trivialmente copiáveis [basic.types] / 9 , se você copiar novamente esses bytes em um objeto real do tipoA*
e, em seguida,delete
o valor disso, isso seria bem definido [basic.types] / 3 . Então, é issoseria ótimo.
Observe que não é o próprio elenco que chama um comportamento indefinido no seu exemplo original, mas sua tentativa subseqüente de ler o valor de um objeto do tipo
A*
que não existe onde o ponteiro obtido pelos pontos de elenco. Tudo o que existe onde o ponteiro aponta é uma sequência de objetos do tipounsigned char
. O tipoA*
não é um tipo que você pode usar para acessar o valor armazenado de um objeto do tipounsigned char
[basic.lval] / 8 …fonte
A* a_ptr; std::memcpy(&a_ptr, buffer.data(), sizeof(a_ptr));
para extrair o ponteiro do buffer. Em vezreinterpret_cast
da pergunta de Timo.unsigned char
lá, talvez mais de um.