2011-10-06 19 views
18

Dato il seguente codice C++:strano GCC problem

struct vertex_type { 
    float x, y, z; 

    //vertex_type() {} 
    //vertex_type(float x, float y, float z) : x(x), y(y), z(z) {} 
}; 

typedef struct { 
    vertex_type vertex[10000]; 
} obj_type; 

obj_type cube = { 
    { 
     {-1, -1, -1}, 
     {1, -1, -1}, 
     {-1, 1, -1}, 
     {1, 1, -1}, 

     {-1, -1, 1}, 
     {1, -1, 1}, 
     {-1, 1, 1}, 
     {1, 1, 1} 
    } 
}; 

int main() { 
    return 0; 
} 

Quando ho aggiunto il (attualmente commentato) costruttori nella vertex_type struct, bruscamente 10-15 secondo aumento nel tempo di compilazione. Bloccato, ho osservato l'assembly generato da gcc (utilizzando -S) e ho notato che la dimensione del codice del codice era centinaia di volte più grande di prima.

... 
movl $0x3f800000, cube+84(%rip) 
movl $0x3f800000, cube+88(%rip) 
movl $0x3f800000, cube+92(%rip) 
movl $0x00000000, cube+96(%rip) 
... 
movl $0x00000000, cube+119996(%rip) 
... 

Ignorando la definizione del costruttore, l'assemblaggio generato era completamente diverso.

.globl cube 
    .data 
    .align 32 
    .type cube, @object 
    .size cube, 120 
cube: 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .zero 24 
    .text 

Ovviamente c'è una differenza significativa nel codice generato dal compilatore. Perché è quello? Inoltre, perché gcc azzera tutti gli elementi in una situazione e non l'altra?

edit: Sto usando i seguenti flag di compilazione: -std=c++0x con g ++ 4.5.2.

+0

Questa è un'ipotesi, ma prova questo: vertex_type(): x(), y(), z() {} – Pubby

+4

@ AlfP.Steinbach Questo è ESATTAMENTE il codice che ho nel mio file. Non c'è nient'altro Qualcuno di voi ha controllato il codice? Esso ha {}. È in linea ... – dcousens

+3

@Alf i costruttori in questione sono commentati. – zwol

risposta

14

Questo è un numero di serie pari a missing optimization in GCC. È dovrebbe essere in grado di generare lo stesso codice per entrambi i casi, ma non può.

Senza i costruttori, il vostro vertex_type è una struttura POD, che GCC può inizializzare istanze statiche/globali al momento della compilazione. Con i costruttori, il meglio che può fare è generare codice per inizializzare l'avvio globale del programma.

+1

Grazie per l'intuizione e il collegamento, ma anche perché azzera gli elementi rimanenti in un caso e non nell'altro? – dcousens

+0

Questa risposta non è corretta. Il codice con il costruttore non dovrebbe nemmeno essere compilato. Vedi la mia risposta. – Nawaz

+0

@Daniel Potrebbe trattarsi di un bug (non correlato). La mia copia di g ++ 4.6.1 azzera i restanti elementi in entrambi i casi (e inoltre * non * genera le istruzioni di 9976 'movl' per riempire gli zeri - usa' .bss' per farlo implicitamente). Non ho gcc 4.5 a portata di mano. – zwol

0

Se si dispone di un costruttore personalizzato, il compilatore deve chiamarlo per tutto il vettore creato. Se non scrivi il tuo, per impostazione predefinita diventa un costruttore generato. Ma poiché nessun tipo è complesso, non è necessario chiamarlo. E l'array è archiviato come una tabella costante nel file binario.

Provare a inserire il costruttore predefinito e lasciarlo vuoto. Naturalmente, può funzionare solo con l'ottimizzazione abilitata

+1

Non è possibile inline un costruttore predefinito per quanto ne so. Il codice che ha pubblicato i costruttori sono implicitamente in linea. – Pubby

+0

È possibile utilizzare l'estensione del compilatore come __forceinline in MSVC – crazyjul