2012-12-13 14 views

risposta

12

Provare a cambiare t[1<<25]={2} a t[1<<25] e la dimensione del * eseguibile ** scenderà a 7.3 K. (Inutile dire che non otterrete i risultati corretti)

Se fosse solo il t[1<<25], non avrebbe preso alcun spazio.

Il problema qui è che l'array viene inizializzato (primo elemento = 2, i successivi 2^25-1 elementi tutti 0) e l'array globale viene inserito nel segmento di dati solo perché è inizializzato.


Generare il gruppo per le 2 versioni ed esaminando la differenza rende ancora più chiaro:

[[email protected] ~]$ diff without_mem.s with_mem.s 
15c15,21 
< .comm t,134217728,32 
--- 
> .globl t 
> .align 32 
> .type t, @object 
> .size t, 134217728 
> t:        ***<- HERE!*** 
> .long 2     
> .zero 134217724 

Come possiamo notare, nella versione originale, l'assemblatore è diretta a generare 2^27 (134217728) byte nel segmento di dati. Quindi diventa parte del file oggetto stesso. (È possibile generare assembly compilando con lo switch -Sgcc -S -fverbose-asm t1.c)


Ma perché 129 MB?
 
    1<< n= 2^n (1 left shifted n times). 
=> 1<<25=2^25. 
    now 1 Integer= 4 bytes =2^2 bytes 
=> 2^25 Integers=2^27 bytes=2^7 * 1 M bytes= 128 MBs 

Per maggiori dettagli, si veda:


* Nota 1: E 'un object file in termini rigorosi.

Nota 2: Come indicato nei commenti, si può anche notare che la dimensione totale del processo (programma in esecuzione) sarà di 129 Mb anche se l'eseguibile è di 7.3K. (La memoria verrà assegnata una volta che il programma inizia l'esecuzione). È possibile visualizzare l'utilizzo della memoria del programma utilizzando il comando top.

Nota 3: Vale la pena sottolineare che ciò vale solo perché t è globale. L'allocazione per i dati locali a una funzione avviene ancora in fase di runtime nello stack. Quindi se t era locale, il file oggetto avrebbe preso solo 7.3K.

Nota 4: le variabili locali inizializzate static, come le variabili globali inizializzate, vengono mantenute anche nel segmento data. A static globale è uguale a come globale eccetto che si limita l'ambito della variabile solo al file corrente.

+0

Anche se la dimensione dell'eseguibile è 7,3 K, la dimensione del processo sarà ancora 130 MB. –

+0

@brianbeuning È abbastanza ovvio, ma viene comunque aggiunto per completezza. – axiom

+0

Questo è sorprendente, sono stato in grado di inizializzare array di notevoli dimensioni _molte volte con GCC e non ho mai visto nulla del genere. Nell'eseguibile vengono inseriti solo dati non uniformi, tutto il resto viene inizializzato con un ciclo simile a 'memset'. Forse sono usate alcune ottimizzazioni di ottimizzazione o flag di debug? – Damon

Problemi correlati