Pregunta

En nuestro código solíamos tener algo como esto:

   *(controller->bigstruct) = ( struct bigstruct ){ 0 };

Esto solía funcionar bien, y luego actualizamos las versiones de GCC y de repente comenzamos a ver desbordamientos de pila. Mirando el ensamblaje, el código GCC antiguo (2.x) básicamente estaba haciendo esto:

memset(controller->bigstruct, 0, sizeof(struct bigstruct));

El nuevo GCC (3.4.x) estaba haciendo esto

   struct bigstruct temp = { 0 };
   controller->bigstruct = temp;

Después de revisar la especificación C99, pude ver por qué; Básicamente, C99 requiere que existan estructuras anónimas en la pila. Es un buen concepto, pero esta estructura era de 4 megabytes, ¡y solo pretendía existir en el montón!

Hemos recurrido a hacer nuestra propia función de "inicializar" que establece explícitamente a los miembros, pero eso es feo y un dolor de cabeza de mantenimiento. No considero a memset una solución adecuada, porque no puedo saber que un valor de bit de 0 es un valor cero apropiado para el tipo (selección de nits, lo sé, pero ahí está; no me importa eso) el compilador lo hace, porque puede saber)

¿Cuál es la forma " correcta " ;, o al menos la mejor manera de inicializar una estructura grande como esta?

Para aclarar furthur por qué creo que memset no es una solución: las reglas de inicialización de los miembros que no se han iniciado explícitamente son las mismas que la inicialización estática, y son las siguientes:    - Si tiene un tipo de puntero, se inicializa a un puntero nulo;    - Si tiene tipo aritmético, se inicializa a (positivo o sin signo) cero;    ...

'memset' establecerá la memoria en cero de patrón de patrón, que no es necesariamente lo mismo. Imagine un sistema que no utiliza números de punto flotante IEEE. Inusual, pero respaldado por C. La representación de 0.0 no tiene que significar "todos los bits cero", podría ser algo conveniente para el procesador.

¿Fue útil?

Solución

memset es el camino a seguir. No tienes muchas alternativas.

Haz algo como:

#define InitStruct(var, type) type var; memset(&var, 0, sizeof(type))

Para que solo tengas que:

InitStruct(st, BigStruct);

Y luego usa st como de costumbre ...

No entiendo cómo " 0 " no es válido " 0 " tipo para una estructura La única forma de " inicializar en masa " una estructura es establecer toda su memoria en un valor; de lo contrario, tendría que crear una lógica adicional para decirle que use un patrón de bits específico por miembro. El mejor " genérico " patrón de bits a utilizar es 0.

Además, esta es la misma lógica que usaste al hacer

*(controller->bigstruct) = *( struct bigstruct ){ 0 };

Por lo tanto, no entiendo tu renuencia a usarlo :)

El primer comentario de esta publicación me hizo investigar un poco antes de llamarlo e idiota y encontré esto:

http://www.lysator.liu.se/ c / c-faq / c-1.html

Muy interesante; Si pudiera votar un comentario, lo haría :)

Dicho esto, su única opción si desea orientar arquitecturas arcaicas con valores nulos distintos a 0 es hacer la inicialización manual de ciertos miembros.

Gracias Thomas Padron-McCarthy! Aprendí algo nuevo hoy :)

Otros consejos

Si no quieres usar memset, siempre puedes declarar una copia estática de tu estructura y usar memcpy, que dará un rendimiento similar. Esto agregará 4 megas a su programa, pero probablemente sea mejor que configurar elementos individuales.

Dicho esto, si GCC estaba usando memset, y era lo suficientemente bueno anteriormente, sugeriría que ahora es lo suficientemente bueno.

Como han dicho otros, memset es el camino a seguir. Sin embargo, no usa memset en objetos C ++, particularmente aquellos con métodos virtuales. El sizeof (foo) incluirá la tabla de punteros de función virtual, y hacer un memset que causará una gran aflicción.

Si memset no resuelve el problema por sí mismo, simplemente haga un memset y luego inicialice cualquier miembro que no sea cero (es decir, sus valores de punto flotante no IEEE).

La función de inicialización privada no es fea sino una buena manera de inicializar objetos (estructuras). Supongo que su estructura no es de 4 MB de punteros, por lo que supongo que la solución debería ser así:

void init_big_struct(struct bigstruct *s)  
{  
    memset(s, 0, sizeof(struct bigstruct));  
    s->some_pointer = NULL; // Multiply this as needed  
}

Por otra parte, nuestro código se ejecuta en más de 20 sistemas operativos integrados y en una gran cantidad de hardware diferente, nunca resuelve ningún problema con solo el memset de la estructura.

hmm: en primer lugar, hacer una función de inicio y establecer cada miembro de forma explícita ES LO CORRECTO: así es como funcionan los constructores en idiomas OO.

y segundo: ¿alguien sabe un hardware que implemente números de punto flotante que no sean IEEE? - Tal vez Commodore 64 o algo más ;-)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top