2010-05-15 10 views
10

Ho un progetto C++ piuttosto semplice, che utilizza la libreria boost :: regex. L'output che sto ottenendo è 3,5 Mb di dimensioni. Come ho capito sto legando staticamente tutti i file boost .CPP, comprese tutte le funzioni/metodi. Forse è possibile in qualche modo istruire il mio linker di utilizzare solo gli elementi necessari da boost, non tutti? Grazie.perché il mio eseguibile in uscita C++ è così grande?

$ c++ —version 
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659) 

Questo è quello che dice size:

$ size a.out 
__TEXT __DATA __OBJC others dec hex 
1556480 69632 0 4296504912 4298131024 100304650 

ho cercato strip:

$ ls -al 
... 3946688 May 21 13:20 a.out 
$ strip a.out 
$ ls -al 
... 3847248 May 21 13:20 a.out 

ps. Questo è come è organizzato il mio codice (forse questa è la causa principale del problema):

// file MyClass.h 
class MyClass { 
    void f(); 
}; 
#include "MyClassImpl.h" 

// file MyClassImpl.h 
void MyClass::f() { 
    // implementation... 
} 

// file main.cpp 
#include "MyClass.h" 
int main(int ac, char** av) { 
    MyClass c; 
    c.f(); 
} 

Cosa ne pensi?

+4

Forse stai costruendo con le informazioni di debug inserite nel file eseguibile. Prova a creare con le ottimizzazioni abilitate. – AraK

+0

Stai compilando le ottimizzazioni? – jalf

+0

Sto usando flag -O3 – yegor256

risposta

15

Forse si compila con simboli di debug abilitati? Ciò potrebbe spiegare una grande porzione della dimensione. Inoltre, come stai determinando la dimensione del binario? Supponendo che tu sia su una piattaforma simile a UNIX stai usando un comando "" o "size" diretto. I due potrebbero dare risultati molto diversi se il binario contiene simboli di debugging. Ad esempio, qui ci sono i risultati che ottengo quando costruisco l'esempio "" credit_card_example.cpp ".

$ g++ -g -O3 foo.cpp -lboost_regex-mt 

$ ls -l a.out 
-rwxr-xr-x 1 void void 483801 2010-05-20 10:36 a.out 

$ size a.out 
    text data  bss  dec  hex filename 
    73330  492  336 74158 121ae a.out 

Risultati simili si verificano quando solo genera il file oggetto:

$ g++ -c -g -O3 foo.cpp 

$ ls -l foo.o 
-rw-r--r-- 1 void void 622476 2010-05-20 10:40 foo.o 

$ size foo.o 
    text data  bss  dec  hex filename 
    49119  4  40 49163 c00b foo.o 

EDIT: Aggiunto alcuni risultati di collegamento statiche ...

Ecco il formato binario durante il collegamento staticamente . E 'più vicino a ciò che stai ricevendo:

$ g++ -static -g -O3 foo.cpp -lboost_regex-mt -lpthread 

$ ls -l a.out 
-rwxr-xr-x 1 void void 2019905 2010-05-20 11:16 a.out 

$ size a.out 
    text data  bss  dec  hex filename 
1204517 5184 41976 1251677 13195d a.out 

E' anche possibile che la maggior parte delle grandi dimensioni è in arrivo da altre librerie della biblioteca Boost.Regex dipende. Sulla mia casella di Ubuntu, le dipendenze per la libreria condivisa Boost.Regex sono i seguenti:

$ ldd /usr/lib/libboost_regex-mt.so.1.38.0 
     linux-gate.so.1 => (0x0053f000) 
     libicudata.so.40 => /usr/lib/libicudata.so.40 (0xb6a38000) 
     libicui18n.so.40 => /usr/lib/libicui18n.so.40 (0x009e0000) 
     libicuuc.so.40 => /usr/lib/libicuuc.so.40 (0x00672000) 
     librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x001e2000) 
     libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x001eb000) 
     libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00110000) 
     libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x009be000) 
     libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x00153000) 
     libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x002dd000) 
     /lib/ld-linux.so.2 (0x00e56000) 

I ICU librerie possono ottenere abbastanza grandi. Oltre al debugging dei simboli, forse sono i principali contributori alla dimensione del tuo binario. Inoltre, nel caso collegato staticamente, sembra che la libreria Boost.Regex in sé è costituito da file oggetto di grandi dimensioni:

$ size --totals /usr/lib/libboost_regex-mt.a | sort -n 
     0  0  0  0  0 regex_debug.o (ex /usr/lib/libboost_regex-mt.a) 
     0  0  0  0  0 usinstances.o (ex /usr/lib/libboost_regex-mt.a) 
     0  0  0  0  0 w32_regex_traits.o (ex /usr/lib/libboost_regex-mt.a) 
    text data  bss  dec  hex filename 
    435  0  0  435  1b3 regex_raw_buffer.o (ex /usr/lib/libboost_regex-mt.a) 
    480  0  0  480  1e0 static_mutex.o (ex /usr/lib/libboost_regex-mt.a) 
    1543  0  36 1579  62b cpp_regex_traits.o (ex /usr/lib/libboost_regex-mt.a) 
    3171  632  0 3803  edb regex_traits_defaults.o (ex /usr/lib/libboost_regex-mt.a) 
    5339  8  13 5360 14f0 c_regex_traits.o (ex /usr/lib/libboost_regex-mt.a) 
    5650  8  16 5674 162a wc_regex_traits.o (ex /usr/lib/libboost_regex-mt.a) 
    9075  4  32 9111 2397 regex.o (ex /usr/lib/libboost_regex-mt.a) 
    17052  8  4 17064 42a8 fileiter.o (ex /usr/lib/libboost_regex-mt.a) 
    61265  0  0 61265 ef51 wide_posix_api.o (ex /usr/lib/libboost_regex-mt.a) 
    61787  0  0 61787 f15b posix_api.o (ex /usr/lib/libboost_regex-mt.a) 
    80811  8  0 80819 13bb3 icu.o (ex /usr/lib/libboost_regex-mt.a) 
116489  8  112 116609 1c781 instances.o (ex /usr/lib/libboost_regex-mt.a) 
117874  8  112 117994 1ccea winstances.o (ex /usr/lib/libboost_regex-mt.a) 
131104  0  0 131104 20020 cregex.o (ex /usr/lib/libboost_regex-mt.a) 
612075  684  325 613084 95adc (TOTALS) 

Si potrebbe arrivare fino a ~ 600K provenienti da Boost.Regex solo se alcuni o tutti coloro i file oggetto vengono collegati al tuo binario.

+1

+1 Prova ad usare boost :: spirit con '-O2 -g'. 250LoC -> 20M, nessuna battuta. I simboli sono così lunghi che si abbattono su Valgrind. I simboli di debug del modello non si scherzano. – academicRobot

+0

Come posso disabilitare le informazioni di debug nell'output? – yegor256

+2

Non compilare con il flag -g o -ggdb. In alternativa, esegui 'strip -g' sul tuo eseguibile per rimuovere i simboli di debug. (Si noti che le informazioni di debug non vengono caricate quando si esegue l'exe, non c'è alcun impatto sulla RAM per mantenerle nell'eseguibile) – nos

2

Se si sta collegando in modo statico, molti linker includeranno solo gli oggetti necessari.

3.5Mb non è così grande - su un sistema PC in modo formato potrebbe dipendere dal sistema operativo ecc

+0

Il mio codice sorgente è solo 10KSLOC, l'enfasi-enfasi è un'altra 6KSLOC.Come potrebbe questo codice (16KSLOC) produrre un eseguibile di 3,5 Mb? – yegor256

+4

@Vin templates, runtime, sommario del preprocessore. loc non è molto significativo – Anycorn

+7

Tutto questo trambusto di circa 3,5 MB ... –

1

Se il tuo ordine di collegamento è impostato correttamente (più dipendente seguito da meno dipendente) il linker deve solo afferrare i simboli effettivamente utilizzati dal programma.Inoltre, un sacco (ma non tutti, e non posso parlare per la regex) la funzionalità di boost è solo intestazione a causa dell'uso del modello.

Più probabile è che le informazioni di debug/tabella dei simboli/ecc. Occupino spazio nel file binario. I nomi dei modelli (ad esempio iostream e i contenitori standard) sono molto lunghi e creano voci grandi nella tabella dei simboli.

Tu non dici quale sistema operativo si sta utilizzando, ma se si tratta di una variante UNIX come test si può effettivamente strip una copia del binario per rimuovere tutte le informazioni in più e vedere quello che è rimasto:

cp a.out a.out.test 
strip a.out.test 
ls -l a.out* 

Su un binario ho provato che rimuoveva circa il 90% delle dimensioni del file. Nota che se lo fai, qualsiasi core sarà abbastanza inutile senza una copia del binario non stoppato su cui eseguire il debug - non avrai nomi di simboli o altro, solo assembly e indirizzi. 3,5 MB è davvero un file minuscolo nei tempi moderni. Molto probabilmente ci sono molte informazioni di debug/simboli anche da soli 10Ksloc di origine.

+0

Non c'è bisogno di striscia il binario per determinare la dimensione senza il debugging di simboli e cruft correlati.Utilizzo semplicemente il comando 'size', come descritto nella mia risposta. – Void

5

Il flag -O3 non ottimizzerà il codice per la dimensione, ma piuttosto per la velocità di esecuzione. Quindi forse per es. alcuni loop-unroling causeranno un file più grande. Prova a compilare con qualche altro flag di ottimizzazione. Il flag -Os ottimizzerà per un piccolo eseguibile.

+0

Anche questo è un buon punto.Compilazione dell'esempio Boost.Regex" 'credit_card_example.cpp'" con '-Os' ha perso la dimensione del file binario di circa 20K in entrambi i casi collegati dinamicamente e staticamente (vedi la mia risposta per i risultati' -O3'). In ogni caso, sarei sorpreso se fosse caduto @ binario di Vincenzo dimensione in modo significativo. Sicuramente vale la pena provare. – Void

+0

+1, non sapevo che l'opzione -Os ha reso le dimensioni più piccole, sicuramente buone informazioni da sapere per il futuro! – shuttle87

0

se si dispone di ldd, è possibile utilizzarlo per verificare se si sta veramente collegando con tutte le librerie di boost.

Un'altra possibilità è che la dimensione è l'effetto collaterale dell'uso di solo le librerie di intestazioni, molte librerie di boost sono del tipo e includendole possono incorporare più codice che si possa credere. È inoltre possibile generare una sorta di esplosione combinatoria a causa dell'uso di diversi parametri del modello.

Per ottenere una diagnostica migliore, provare a creare un programma veramente breve utilizzando espressioni regolari e visualizzare le dimensioni ottenute. Se il tuo programma è veramente corto, 3,5 Mo è abbastanza grande. Il mio attuale programma projet utilizza anche BOOST (ma non regex) e ha le stesse dimensioni. Ma sto parlando di circa 20000 righe di C++. Quindi dovrebbe esserci una presa da qualche parte.

1

Si dice di avere 3 file. Per me, MyClassImpl.h è probabilmente un .cpp poiché contiene un'implementazione.

Ad ogni modo, se si stanno effettivamente compilando due file, tra cui boost :: regex, si finirà per avere due volte la dimensione di boost :: regex (proprio se si utilizza la stessa funzionalità in entrambi i file si avrà il doppio del costo nello spazio).

Ciò è dovuto al fatto che la maggior parte delle funzionalità di potenziamento sono modelli in linea.

best,

Problemi correlati