2012-06-08 10 views
7

Esto es puramente hipotético, pero no estoy seguro de si el siguiente código dará como resultado un comportamiento indefinido según las especificaciones de C++. Me gustaría hacer una copia de los bytes en un objeto, arruinar el objeto sobreescribiéndolo con ceros, y luego copiar los viejos bytes. ¿Puedo hacerlo sin causar un comportamiento indefinido?¿Puedo clonar los bytes de un objeto C++, sobrescribir los bytes originales y luego copiar esos bytes?

Código de ejemplo:

NonPODType o; 
char bytes[sizeof(o)]; 

memcpy(bytes, &o, sizeof(o)); 
memset(&o, 0, sizeof(o)); 
memcpy(&o, bytes, sizeof(o)); 
+1

No creo que cause ningún problema extraño, pero ¿por qué harías eso? Desde mi entendimiento, el resultado neto es cero cambio –

+1

pregunta interesante. Si la respuesta es "No", sería interesante ver un ejemplo específico que no funciona. Por supuesto, tal ejemplo podría no existir en las implementaciones actuales. –

+0

Definitivamente se rompe para una clase con miembros volátiles (ya que el estado puede cambiar entre copiar y establecer). –

Respuesta

9

En general, no. Existe una garantía explícita de que esto funciona para tipos triviales que pueden copiarse en §3.9/2, pero no hay tal cosa para otros tipos.

Para cualquier objeto (distinto de un subobjeto de la clase base) de trivialmente copiable tipo T, si o no el objeto contiene un valor válido de tipo T, los bytes subyacentes (1,7) que constituyen el objeto puede se copiará en una matriz de char o unsigned char. Si el contenido de la matriz de char o unsigned char se copia de nuevo en el objeto, el objeto deberá mantener posteriormente su valor original. [Ejemplo:

#define N sizeof(T) 
char buf[N]; 
T obj; 
// obj initialized to its original value 
std::memcpy(buf, &obj, N); 
// between these two calls to std::memcpy, 
// obj might be modified 
std::memcpy(&obj, buf, N); 
// at this point, each subobject of obj of scalar type 
// holds its original value 

ejemplo -end]

+0

+1 Cita perfecta con un fragmento de código perfecto. – Nawaz

+0

¡Impresionante! Dicho esto, ¿sabes qué se rompe específicamente si T no se puede copiar de manera trivial? – templatetypedef

+0

@templatetypedef He estado tratando de encontrar alguna razón que lo rompa, pero, a menos que accedas a los bytes copiados, tengo problemas para encontrar un ejemplo convincente (que no implique una implementación hipotética de Hell ++) No sé si eso solo se debe a mi falta de imaginación. –

1

En general, sí. La única forma en que las cosas se rompen es si accede al objeto después de destruir el objeto y antes de la restitución de sus datos:

memset (& o, 0, sizeof (o));

obj.doAlgo(); < --- breaks

memcpy (& o, bytes, sizeof (o));

+0

Estaba asumiendo que no hay operaciones intermedias en el objeto mientras que sus bytes se han destruido temporalmente. ¡Pero gracias por señalar esto! – templatetypedef

+0

¿Prohibiría algo una implementación en C++ mantener una lista vinculada de * todos * objetos que no sean POD y escanear esa lista cada vez que se modifica cualquier cosa en la memoria (pero con respecto a los cambios generados por compiladores a la estructura como atómicos)? Tal cosa sería terriblemente lenta, por supuesto, pero ¿algo lo prohibiría? – supercat

Cuestiones relacionadas