Nasz kod zawiera strukturę POD (Plain Old Datastructure) (jest to podstawowa struktura c ++, która zawiera inne struktury i zmienne POD, które muszą zostać zainicjowane na początku).
Na podstawie tego, co przeczytałem , wydaje się, że:
myStruct = (MyStruct*)calloc(1, sizeof(MyStruct));
powinien zainicjować wszystkie wartości na zero, tak jak:
myStruct = new MyStruct();
Jednakże, gdy struktura jest inicjalizowana w drugi sposób, Valgrind później narzeka, że „warunkowy skok lub ruch zależy od niezainicjowanych wartości”, gdy te zmienne są używane. Czy moje rozumienie jest tutaj błędne, czy też Valgrind rzuca fałszywe alarmy?
new MyStruct()
nie było wymagane ustawianie żadnych bajtów wypełniających w C ++ 03. W C ++ 0x jest. Wszelkie bity wypełnienia zostaną ustawione na 0 w C ++ 0x.Odpowiedzi:
W C ++ klasy / struktury są identyczne (pod względem inicjalizacji).
Struktura inna niż POD może równie dobrze mieć konstruktora, dzięki czemu może inicjować członków.
Jeśli twoja struktura jest POD, możesz użyć inicjatora.
struct C { int x; int y; }; C c = {0}; // Zero initialize POD
Alternatywnie możesz użyć domyślnego konstruktora.
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).
Myślę, że Valgrind narzeka, ponieważ tak właśnie działało C ++. (Nie jestem dokładnie pewien, kiedy C ++ został zaktualizowany z domyślną konstrukcją inicjalizacji zerowej). Najlepszym rozwiązaniem jest dodanie konstruktora, który inicjalizuje obiekt (konstrukcje są dozwolonymi konstruktorami).
Na marginesie:
wielu początkujących próbuje docenić init:
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();
Szybkie wyszukiwanie „Najbardziej irytującej analizy” zapewni lepsze wyjaśnienie niż ja.
źródło
C()
ale wydaje się , że masz rację .T
,T()
ma zawsze zero zainicjowany przez skalarne podobiekty. Nazwa inicjalizacji najwyższego poziomu została nazwana inaczej w C ++ 98 niż w C ++ 03 („inicjalizacja domyślna” a „inicjalizacja wartości”), ale efekt końcowy dla POD jest taki sam. Zarówno C ++ 98, jak i C ++ 03 miałyby wszystkie wartości równe zero.C c();
niestety nie jest deklaracją zmiennej, ale raczej deklaracją funkcji (funkcja o nazwie „c”, która nie przyjmuje parametrów i zwraca obiekt typu C). Google: Most Vexing ParseC c(4);
Jest prawidłową deklaracją zmiennej.Z tego, co nam powiedziałeś, wygląda na to, że valgrind jest fałszywie dodatni.
new
Składnia z()
cenić zainicjować obiekt, zakładając, że jest POD.Czy to możliwe, że część Twojej struktury nie jest w rzeczywistości POD, a to zapobiega oczekiwanej inicjalizacji? Czy jesteś w stanie uprościć swój kod do postaci wysyłanego przykładu, który nadal oznacza błąd Valgrind?
Alternatywnie, być może Twój kompilator w rzeczywistości nie inicjalizuje wartości struktur POD.
W każdym razie prawdopodobnie najprostszym rozwiązaniem jest napisanie konstruktora (-ów) zgodnie z potrzebami dla struktury / części podrzędnych.
źródło
Piszę kod testowy:
#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 ++ skompiluj i uruchom:
./a.out 132 az:0x2b0000002a bz:0 a:854191480 yend b:0 yend aa:854190968 yend ba:0 yend
źródło
new sc;
vsnew sc();
. Pomyślałbym, że brakujące pareny to błąd. Ale wydaje się, że to pokazuje, że odpowiedź jest prawidłowa (Musisz zainicjować wszystkich członków, których masz w swojej strukturze, np:
struct MyStruct { private: int someInt_; float someFloat_; public: MyStruct(): someInt_(0), someFloat_(1.0) {} // Initializer list will set appropriate values };
źródło
Ponieważ jest to struktura POD, zawsze możesz ustawić ją na 0 - może to być najłatwiejszy sposób na zainicjowanie pól (zakładając, że jest to właściwe).
źródło
Wydaje mi się, że to najłatwiejszy sposób. Składowe struktury można zainicjować za pomocą nawiasów klamrowych „{}”. Na przykład poniżej przedstawiono prawidłową inicjalizację.
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}; }
Istnieją dobre informacje o strukturach w języku c ++ - https://www.geeksforgeeks.org/structures-in-cpp/
źródło