Nuestro código involucra una estructura POD (Plain Old Datastructure) (es una estructura c ++ básica que tiene otras estructuras y variables POD que deben inicializarse al principio).
Basado en lo que he leído , parece que:
myStruct = (MyStruct*)calloc(1, sizeof(MyStruct));
debería inicializar todos los valores a cero, al igual que:
myStruct = new MyStruct();
Sin embargo, cuando la estructura se inicializa de la segunda forma, Valgrind luego se queja de que "el salto o movimiento condicional depende de valores no inicializados" cuando se utilizan esas variables. ¿Mi comprensión es defectuosa aquí, o Valgrind arroja falsos positivos?
new MyStruct()
no fue necesario establecer bytes de relleno en C ++ 03. En C ++ 0x lo es. Los bits de relleno se establecerán en 0 en C ++ 0x.Respuestas:
En C ++, las clases / estructuras son idénticas (en términos de inicialización).
Una estructura que no sea POD también puede tener un constructor para que pueda inicializar miembros.
Si su estructura es un POD, entonces puede usar un inicializador.
struct C { int x; int y; }; C c = {0}; // Zero initialize POD
Alternativamente, puede usar el constructor predeterminado.
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).
Creo que valgrind se queja porque así es como solía funcionar C ++. (No estoy exactamente seguro de cuándo se actualizó C ++ con la construcción predeterminada de inicialización cero). Su mejor opción es agregar un constructor que inicialice el objeto (las estructuras son constructores permitidos).
Como nota al margen:
muchos principiantes intentan valorar 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();
Una búsqueda rápida del "análisis más irritante" proporcionará una mejor explicación que yo.
fuente
C()
, pero parece que tienes razón .T
,T()
tiene siempre cero inicializan los subobjetos escalares. El nombre de la inicialización de nivel superior se llamó de manera diferente en C ++ 98 que en C ++ 03 ("inicialización predeterminada" frente a "inicialización de valor"), pero el efecto final para los POD es el mismo. Tanto C ++ 98 como C ++ 03 tendrían todos los valores en cero.C c();
desafortunadamente no es una declaración de variable sino más bien una declaración hacia adelante de una función (una función llamada 'c' que no toma parámetros y devuelve un objeto de tipo C). Google: análisis más irritanteC c(4);
Es una declaración de variable válida.Por lo que nos ha dicho, parece ser un falso positivo en valgrind. La
new
sintaxis con()
debe inicializar el valor del objeto, asumiendo que es POD.¿Es posible que alguna subparte de su estructura no sea realmente POD y eso impida la inicialización esperada? ¿Puede simplificar su código en un ejemplo postable que aún marca el error valgrind?
Alternativamente, quizás su compilador no inicialice realmente las estructuras POD.
En cualquier caso, probablemente la solución más simple es escribir constructor (es) según sea necesario para la estructura / subpartes.
fuente
Escribo un código de prueba:
#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 ++ compila y ejecuta:
./a.out 132 az:0x2b0000002a bz:0 a:854191480 yend b:0 yend aa:854190968 yend ba:0 yend
fuente
new sc;
vsnew sc();
. Habría pensado que los parens faltantes eran un error. Pero esto parece demostrar que la respuesta es correcta (que no init a 0 cuando se utiliza el constructor predeterminado.)Necesita inicializar los miembros que tenga en su estructura, por ejemplo:
struct MyStruct { private: int someInt_; float someFloat_; public: MyStruct(): someInt_(0), someFloat_(1.0) {} // Initializer list will set appropriate values };
fuente
Dado que es una estructura POD, siempre puede configurarlo en 0; esta podría ser la forma más fácil de inicializar los campos (suponiendo que sea apropiado).
fuente
Esa me parece la forma más fácil. Los miembros de la estructura se pueden inicializar usando llaves '{}'. Por ejemplo, a continuación se muestra una inicialización válida.
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}; }
Hay buena información sobre estructuras en c ++: https://www.geeksforgeeks.org/structures-in-cpp/
fuente