memcpy und alignment
-
Hallo,
ich habe folgenden (nicht meinen) code vor mir:
struct blabla { int a; int b; double c; double d; anderes_struct e; anderes_struct f; blabla(){memset(this,0,sizeof(blabla));}; blabla(const blabla&other){memcpy(this,&other,sizeof(blabla));}; blabla& operator=(const blabla&other){memcpy(this,&other,sizeof(blabla));return *this;}; }Ist die Verwendung von memcpy/memset für structs bestehen nur aus POD okay? Mir persönlich fällt da memory alignment im Release Modus als Mögliches Problem auf.
Wie sieht es aus wie in diesem Fall, wenn auch andere structs, oder Klassen die nicht nur aus POD bestehen ein Teil der Klasse sind?
-
Nur als Anmerkung: Structs/Klassen mit einem Custom-Default-Constructor sind keine PODs
mehr.
-
Der implizit deklarierte Kopierkonstruktor und Zuweisungsoperator vom Compiler kopiert alles schon für dich, und wenn man alles ausnullen will dann muss man auch nicht
memsetverwenden, sondern kann die Klasse mit{}initialisieren - wenn diese ein POD wäre (was hier nicht der Fall ist), dann würde dieser Initializer das Objekt zero-initializen, was soviel heißt wie: Padding ausnullen, alle Skalare auf Null setzen, und andere Member wiederum zero-initializen.anderes_struct
Was ist das für eine Struktur? Ein POD-Typ?
Du brauchst ja nach einer Kopie nicht auch das gleiche Padding, oder?

theta schrieb:
Nur als Anmerkung: Structs/Klassen mit einem Custom-Default-Constructor sind keine PODs
mehr.
Standardlayout hat es allerdings.
-
Arcoth schrieb:
Was ist das für eine Struktur? Ein POD-Typ?
struct anderes_struct { int row,col; unsigned char value; anderes_struct():row(0),col(0),value(0){}; anderes_struct(int r,int c):row(r),col(c),value(0){}; anderes_struct(int r,int c,unsigned char v):row(r),col(c),value(v){}; anderes_struct(unsigned int r,unsigned int c):row((int)r),col((int)c),value(0){}; anderes_struct(unsigned int r,unsigned int c,unsigned char v):row((int)r),col((int)c),value(v){}; anderes_struct(double r,double c,unsigned char v); anderes_struct(double r,double c); anderes_struct( const anderes_struct &other); anderes_struct(const anderes_struct2 &other); anderes_struct& operator=(const anderes_struct& other); anderes_struct& operator=(const anderes_struct2& other); anderes_struct& operator+=(const anderes_struct&other); anderes_struct& operator-=(const anderes_struct&other); anderes_struct operator+ (const anderes_struct&other); anderes_struct operator- (const anderes_struct&other); anderes_struct2 operator+ (const anderes_struct2&other); anderes_struct2 operator- (const anderes_struct2&other); anderes_struct operator* (int skalar); anderes_struct operator* (double skalar); anderes_struct operator/ (int skalar); anderes_struct operator/ (double skalar); anderes_struct& operator/=(int skalar); anderes_struct& operator/=(double skalar); };
-
Übrigens: §3.9/2 und /3 gelten auch nur für trivial kopierbare Typen. Deine Klasse ist offensichtlich nicht trivial kopierbar, also muss
*thisnach der Kopie in Zeilen 12 und 13 nicht denselben Wert haben wieother.
Ob das UB ist, kann ich aber nicht mit Sicherheit sagen (sieht irgendwie nicht danach aus, halt nur danach, dass das Ergebnis nicht festgelegt ist), das weiß bestimmt camper.anderes_structist nach deinem Code-Schnipsel kein POD, und auch nicht trivial kopierbar.
-
Arcoth schrieb:
Übrigens: §3.9/2 und /3 gelten auch nur für trivial kopierbare Typen.
Was ist mit " §3.9/2 und /3" gemeint? Wäre dir für einen Link dankbar.
-
dasdsad schrieb:
Arcoth schrieb:
Übrigens: §3.9/2 und /3 gelten auch nur für trivial kopierbare Typen.
Was ist mit " §3.9/2 und /3" gemeint? Wäre dir für einen Link dankbar.
Das sind Standardparagraphen:
§3.9/2 schrieb:
For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (1.7) making up the object can be copied into an array of
charorunsigned char. If the content of the array of char or unsigned char is copied back into the
object, the object shall subsequently hold its original value.#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§3.9/3 schrieb:
For any trivially copyable type
T, if two pointers toTpoint to distinctTobjectsobj1andobj2, where
neitherobj1norobj2is a base-class subobject, if the underlying bytes (1.7) making upobj1are copied
intoobj2,obj2shall subsequently hold the same value asobj1.T* t1p; T* t2p; // provided that t2p points to an initialized object ... std::memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of trivially copyable type in *t1p contains // the same value as the corresponding subobject in *t2p