Unser Code enthält eine POD-Struktur (Plain Old Datastructure) (es ist eine grundlegende c ++ - Struktur, die andere Strukturen und POD-Variablen enthält, die zu Beginn initialisiert werden müssen.)
Basierend auf einem, was ich gelesen habe , scheint es, dass:
myStruct = (MyStruct*)calloc(1, sizeof(MyStruct));
sollte alle Werte auf Null initialisieren, ebenso wie:
myStruct = new MyStruct();
Wenn die Struktur jedoch auf die zweite Weise initialisiert wird, beschwert sich Valgrind später, dass "bedingte Sprünge oder Bewegungen von nicht initialisierten Werten abhängen", wenn diese Variablen verwendet werden. Ist mein Verständnis hier fehlerhaft oder wirft Valgrind falsch positive Ergebnisse?
new MyStruct()
in C ++ 03 keine Auffüllbytes festgelegt werden mussten. In C ++ 0x ist es. Alle Füllbits werden in C ++ 0x auf 0 gesetzt.Antworten:
In C ++ sind Klassen / Strukturen identisch (in Bezug auf die Initialisierung).
Eine Nicht-POD-Struktur kann auch einen Konstruktor haben, um Mitglieder zu initialisieren.
Wenn Ihre Struktur ein POD ist, können Sie einen Initialisierer verwenden.
struct C { int x; int y; }; C c = {0}; // Zero initialize POD
Alternativ können Sie den Standardkonstruktor verwenden.
C c = C(); // Zero initialize using default constructor C c{}; // Latest versions accept this syntax. C* c = new C(); // Zero initialize a dynamically allocated object. // Note the difference between the above and the initialize version of the constructor. // Note: All above comments apply to POD structures. C c; // members are random C* c = new C; // members are random (more officially undefined).
Ich glaube, Valgrind beschwert sich, weil C ++ früher so funktioniert hat. (Ich bin nicht genau sicher, wann C ++ mit der Standardkonstruktion ohne Initialisierung aktualisiert wurde). Am besten fügen Sie einen Konstruktor hinzu, der das Objekt initialisiert (Strukturen sind Konstruktoren zulässig).
Als Randnotiz:
Viele Anfänger versuchen, init zu bewerten:
C c(); // Unfortunately this is not a variable declaration. C c{}; // This syntax was added to overcome this confusion. // The correct way to do this is: C c = C();
Eine schnelle Suche nach "Most Vexing Parse" liefert eine bessere Erklärung als ich.
quelle
C()
, aber es scheint, dass Sie Recht haben .T
,T()
hat immer Null die skalare Subobjekte initialisiert. Der Name der Toplevel-Initialisierung wurde in C ++ 98 anders als in C ++ 03 genannt ("Standardinitialisierung" vs. "Wertinitialisierung"), aber der Endeffekt für PODs ist der gleiche. Sowohl in C ++ 98 als auch in C ++ 03 wären alle Werte Null.C c();
leider keine Variablendeklaration, sondern eine Vorwärtsdeklaration einer Funktion (Eine Funktion namens 'c', die keine Parameter akzeptiert und ein Objekt vom Typ C zurückgibt). Google: Most Vexing ParseC c(4);
Ist eine gültige Variablendeklaration.Nach dem, was Sie uns gesagt haben, scheint es in Valgrind ein falsches Positiv zu sein. Die
new
Syntax mit()
sollte das Objekt mit einem Wert initialisieren, vorausgesetzt, es ist POD.Ist es möglich, dass ein Teil Ihrer Struktur kein POD ist und dies die erwartete Initialisierung verhindert? Können Sie Ihren Code in ein postbares Beispiel vereinfachen, das den Valgrind-Fehler weiterhin kennzeichnet?
Alternativ kann es sein, dass Ihr Compiler POD-Strukturen nicht wirklich wertinitialisiert.
In jedem Fall besteht die wahrscheinlich einfachste Lösung darin, Konstruktoren zu schreiben, die für die Struktur / Unterteile erforderlich sind.
quelle
Ich schreibe einen Testcode:
#include <string> #include <iostream> #include <stdio.h> using namespace std; struct sc { int x; string y; int* z; }; int main(int argc, char** argv) { int* r = new int[128]; for(int i = 0; i < 128; i++ ) { r[i] = i+32; } cout << r[100] << endl; delete r; sc* a = new sc; sc* aa = new sc[2]; sc* b = new sc(); sc* ba = new sc[2](); cout << "az:" << a->z << endl; cout << "bz:" << b->z << endl; cout << "a:" << a->x << " y" << a->y << "end" << endl; cout << "b:" << b->x << " y" << b->y << "end" <<endl; cout << "aa:" << aa->x << " y" << aa->y << "end" <<endl; cout << "ba:" << ba->x << " y" << ba->y << "end" <<endl; }
g ++ kompilieren und ausführen:
./a.out 132 az:0x2b0000002a bz:0 a:854191480 yend b:0 yend aa:854190968 yend ba:0 yend
quelle
new sc;
vsnew sc();
. Ich hätte gedacht, dass die fehlenden Parens ein Fehler waren. Dies scheint jedoch zu zeigen, dass die Antwort korrekt ist (sie wird auf 0 gesetzt, wenn Sie den Standardkonstruktor verwenden.)Sie müssen alle Mitglieder initialisieren, die Sie in Ihrer Struktur haben, z.
struct MyStruct { private: int someInt_; float someFloat_; public: MyStruct(): someInt_(0), someFloat_(1.0) {} // Initializer list will set appropriate values };
quelle
Da es sich um eine POD-Struktur handelt, können Sie sie jederzeit auf 0 setzen. Dies ist möglicherweise der einfachste Weg, um die Felder zu initialisieren (sofern dies angemessen ist).
quelle
Das scheint mir der einfachste Weg zu sein. Strukturelemente können mit geschweiften Klammern '{}' initialisiert werden. Das Folgende ist beispielsweise eine gültige Initialisierung.
struct Point { int x, y; }; int main() { // A valid initialization. member x gets value 0 and y // gets value 1. The order of declaration is followed. struct Point p1 = {0, 1}; }
Es gibt gute Informationen zu Strukturen in c ++ - https://www.geeksforgeeks.org/structures-in-cpp/
quelle