Pergunta

Em nosso código estamos habituados a ter algo como isto:

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

Este utilizado para um grande trabalho, e então nós atualizado versões do GCC e de repente começou a ver estouros de pilha. Olhando para a montagem, o código GCC idade (2.x) foi basicamente fazer isso:

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

O novo GCC (3.4.x) estava fazendo isso

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

Depois de analisar a especificação C99, eu podia ver o porquê; C99 basicamente exige que existem estruturas anônimos na pilha. É um conceito bom, mas esta estrutura foi de 4 megabytes grande, e sempre apenas destinado a existir no montão!

Temos recorrido a fazer nossa própria função 'initialize' que explicitamente define os membros, mas isso é feio e uma dor de cabeça de manutenção. Eu não considero memset uma solução adequada, porque eu não posso saber que um pouco de valor de 0 é um zero valor apropriado para o tipo (picuinhas, eu sei, mas você está lá; eu não me importo que o compilador faz isso, porque pode saber)

O que é a "correta", ou pelo menos melhor, maneira de inicializar uma grande estrutura como esta?

Para furthur esclarecer por que eu acho que memset não é uma solução: As regras de inicialização de membros não explicitamente inicializadas são o mesmo que inicialização estática, e são os seguintes: - Se ele tem o tipo de ponteiro, ele é inicializado para um ponteiro nulo; - Se ele tem tipo aritmética, é inicializado para (positivo ou sem sinal) zero; ...

'memset' irá definir a memória para bit-padrão de zero, o que não é necessariamente a mesma coisa. Imagine um sistema que não usa números IEEE ponto flutuante. Incomum, mas apoiado por C. A representação de 0.0 não tem de significar "todos os bits zero", poderia ser qualquer coisa conveniente para o processador.

Foi útil?

Solução

memset é o caminho a percorrer. Você não tem muitas alternativas.

fazer algo como:

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

Assim que você só tem que:

InitStruct(st, BigStruct);

E, em seguida, usar st como de costume ...

Eu não entendo como "0" não é um "0" tipo válido para um struct. A única maneira de "Inicializar massa" um struct é definir toda a sua memória para um valor; caso contrário, você teria que fazer lógica extra para dizer-lhe para usar um padrão de bits específica por membro. O padrão melhor "genérico" bit para uso é 0.

Além disso - esta é a mesma lógica que você usou ao fazer

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

Portanto, eu não obter a sua relutância em usá-lo:)

O primeiro comentário a este post me fez fazer alguma pesquisa antes de eu o chamei e idiota e eu encontrei isto:

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

Muito interessante; se eu poderia votar-se um comentário que eu faria:)

Dito -. Sua única opção se você deseja direcionar arquiteturas arcaicas com-0 não valores nulos é ainda fazer a inicialização manual para certos membros

Graças Thomas Padron-McCarthy! Eu aprendi algo novo hoje:)

Outras dicas

Se você não quiser usar memset, você sempre pode declarar uma cópia estática de sua estrutura e uso memcpy, o que irá proporcionar um desempenho similar. Isto irá adicionar 4 megas para o seu programa, mas é provavelmente melhor do que a criação elementos individuais.

Dito isto, se GCC estava usando memset, e foi bom o suficiente anteriormente, gostaria de sugerir é bom o suficiente agora.

Como já foi dito, memset é o caminho a percorrer. No entanto, não uso memset em objetos C ++, particularmente aqueles com métodos virtuais. O sizeof( foo ) irá incluir a tabela de ponteiros de função virtuais, e fazendo um memset em que irá causar graves dor.

Se memset não resolver o problema por si só, basta fazer uma memset e então inicializar quaisquer membros que devem ser zero não (ou seja, os seus valores de ponto flutuante não-IEEE).

função de inicialização Privada não é feio sim uma boa maneira OO para inicializar objetos (estruturas). Presumo que a sua estrutura não é 4MB de ponteiros, então eu diria que a solução deve ser assim:

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

De outro lado o nosso código está sendo executado em mais de 20 sistemas operacionais embutidos e grande número de diferentes hardwares, nunca se encontram qualquer problema com apenas memset da estrutura.

hmm - em primeiro lugar fazer uma função init e definindo cada membro explicitamente é a coisa certa -. Ele, é a maneira construtores em linguagens OO trabalho

e segunda - alguém sabe um hardware que implementa números de ponto flutuante não IEEE? - talvez Commodore 64 ou somethig; -)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top