Domanda

test.c:

int main()
{
    return 0;
}

Non ho usato nessun bandiere (io sono un newb a gcc), solo il comando:

gcc test.c

Ho usato l'ultima TDM build di GCC su win32. L'eseguibile risultante è quasi 23KB, troppo grande per un programma vuoto.

Come posso ridurre le dimensioni del file eseguibile?

È stato utile?

Soluzione

Non seguire i suoi suggerimenti, ma per l'amor di divertimenti, leggere questo ' storia ' di fare il più piccolo binario ELF possibile.

Altri suggerimenti

  

Come posso ridurre le sue dimensioni?

  • Non farlo. Basta sprecare il vostro tempo.
  • -s bandiera spogliare simboli (gcc -s)

Per impostazione predefinita alcune librerie standard (ad esempio C runtime) collegati con il vostro eseguibile. Vedi le chiavi --nostdlib --nostartfiles --nodefaultlib per i dettagli. opzioni di collegamento descritto qui .

Per seconda opzione vero programma è quello di provare opzioni di ottimizzazione , per esempio -Os (ottimizzazione per le dimensioni).

rinunciare. Su Linux x86, gcc 4.3.2 produce un binario 5K. Ma aspetta! Questo è con il collegamento dinamico! Il staticamente binario collegato è più di mezzo meg: 516K. Rilassatevi e imparare a convivere con la pesantezza.

E hanno detto Modula-3 non sarebbe mai andare da nessuna parte a causa di un 200K ciao binario mondo!


Nel caso in cui ci si chiede cosa sta succedendo, la libreria GNU C è strutturata in modo da includere alcune funzioni se il programma dipende da loro o no. Queste caratteristiche includono tali curiosità come malloc e gratuito, dlopen, qualche elaborazione delle stringhe, e tutta una bucketload di roba che sembra avere a che fare con locali e l'internazionalizzazione, anche se non riesco a trovare nessuna pagine rilevanti .

La creazione di piccoli eseguibili per i programmi che richiedono servizi minimi è non un obiettivo di progettazione per glibc. Per essere onesti, è stato anche non un obiettivo di progettazione per ogni sistema run-time che abbia mai lavorato (circa una mezza dozzina).

In realtà, se il codice non fa nulla, è anche giusto che il compilatore crea ancora un eseguibile? ; -)

Bene, su Windows qualsiasi eseguibile sarebbe ancora hanno una dimensione, anche se può essere ragionevole piccola. Con il vecchio sistema MS-DOS, un'applicazione completa do-nothing sarebbe solo un paio di byte. (Credo quattro byte di utilizzare l'interrupt 21h per chiudere il programma.) Poi di nuovo, quelle applicazioni sono stati caricati direttamente nella memoria. Quando il formato EXE è diventato più popolare, le cose sono cambiate un po '. Ora eseguibili avuto ulteriori informazioni sul processo stesso, come il trasferimento di segmenti di codice e dati più alcune somme di controllo e le informazioni sulla versione. L'introduzione di Windows aggiunto un altro colpo di testa al formato, per raccontare MS-DOS che non poteva eseguire il file eseguibile in quanto necessario per eseguire sotto Windows. E di Windows avrebbe riconosciuto senza problemi. Naturalmente, il formato eseguibile è stato anche ampliato con informazioni sulle risorse, come immagini bitmap, icone e forme di dialogo e molto altro ancora.

Un eseguibile do-nothing sarebbe al giorno d'oggi essere compreso tra 4 e 8 kilobyte in termini di dimensioni, a seconda del compilatore e ogni metodo che hai utilizzato per ridurre la sua dimensione. Sarebbe in una dimensione in cui UPX sarebbe effettivamente causare eseguibili più grandi! Ulteriori byte nel vostro eseguibile potrebbero essere aggiunti perché si è aggiunto alcune librerie di codice. Soprattutto librerie con dati o risorse inizializzati aggiungerà una notevole quantità di byte. L'aggiunta di informazioni di debug aumenta anche la dimensione del file eseguibile.

Ma mentre tutto questo ha un bel esercizio a ridurre le dimensioni, si potrebbe chiedere se è pratico di continuare solo preoccupare di gonfiore delle applicazioni. I moderni dischi rigidi saranno dividere i file in segmenti e per davvero dischi di grandi dimensioni, la differenza sarebbe molto piccola. Tuttavia, la quantità di problemi che ci vuole per mantenere le dimensioni il più piccolo possibile rallentare la velocità di sviluppo, a meno che non sei uno sviluppatore esperto che viene utilizzato per queste ottimizzazioni. Questi tipi di ottimizzazioni non tendono a migliorare le prestazioni e considerando lo spazio su disco media della maggior parte dei sistemi, non vedo il motivo per cui sarebbe pratico. (Ancora, faccio a ottimizzare il proprio codice in modo simile, ma poi di nuovo, ho una buona esperienza con queste ottimizzazioni.)


Interessato alla EXE intestazione ? E 'inizia con le lettere MZ, per "Mark Zbikowski". La prima parte è il vecchio stile di intestazione MS-DOS per gli eseguibili e viene utilizzato come uno stub per MS-DOS dicendo che il programma è non un eseguibile di MS-DOS. (Nella binario, è possibile trovare il testo che fondamentalmente è tutto ciò che fa 'Questo programma non può essere eseguito in modalità DOS.':. Visualizza il messaggio seguente è l'intestazione del PE, che Windows riconoscerà e usare al posto di MS-DOS intestazione. Si inizia con le lettere PE per Portable Executable . Dopo questo secondo intestazione ci sarà l'eseguibile stesso, diviso in diversi blocchi di codice e dati. l'intestazione contiene le tabelle di riallocazione speciali che dice al sistema operativo in cui per caricare un blocco specifico. e se è possibile mantenere questo per un limite, l'eseguibile finale può essere minore di 4 KB, ma il 90% sarebbe allora le informazioni di intestazione e alcuna funzionalità.

Mi piace il modo in cui il DJGPP FAQ affrontato questo molti molti anni fa :

  

In generale, a giudicare dimensioni di codici, cercando nella dimensione del "ciao" programmi è priva di senso, in quanto tali programmi sono costituiti in gran parte del codice di avvio. ... La maggior parte della potenza di tutte queste caratteristiche va sprecata in "Hello" programmi. Non v'è alcun punto in esecuzione tutto quel codice solo per stampare una stringa di 15 byte e uscita.

Qual è lo scopo di questo esercizio?

Anche con partire un linguaggio di livello come C, c'è ancora un sacco di messa a punto che deve accadere prima che principale può essere chiamato. Alcuni di che l'installazione è gestita dal caricatore (che necessita di determinate informazioni), alcuni è gestito dal codice che chiama principale. E poi c'è probabilmente un po 'di codice della libreria che qualsiasi programma normale dovrebbe avere. Almeno, c'è probabilmente i riferimenti alle librerie standard, se sono in DLL.

Esaminando il formato binario del programma vuoto è un esercizio inutile in sé. Vi dice niente. Se si vuole imparare qualcosa circa la dimensione del codice, provare a scrivere i programmi non vuoti (e preferibilmente non banali). Confronta i programmi che utilizzano le librerie standard con programmi che fanno tutto da soli.

Se si vuole veramente sapere cosa sta succedendo in quel binario (e perché è così grande), quindi trovare il formato eseguibile ottenere uno strumento dump binario e prendere la cosa a parte.

Cosa significa 'size a.out' ti ha detto la dimensione dei segmenti di codice, dati, e BSS? La maggior parte del codice è probabile che sia il codice di partenza (crt0.o classicamente su macchine Unix) che viene richiamato dalla o / s e funziona configurare (come smistamento di questi parametri in argc, argv) prima di richiamare main().

strip Eseguire sul binario per sbarazzarsi dei simboli. Con gcc version 3.4.4 (cygming speciale) I drop da 10k a 4K.

Si può provare a collegare un tempo di funzionamento personalizzato (la parte che chiama principale) per impostare l'ambiente di runtime. Tutti i programmi utilizzano la stessa per impostare l'ambiente di runtime che viene fornito con gcc, ma per il vostro eseguibile non avete bisogno di dati o di memoria zero'ed. Il mezzo si potrebbe sbarazzarsi di funzioni di libreria non utilizzate come memset / memcpy e ridurre la dimensione CRT0. Quando alla ricerca di informazioni su questo sguardo al GCC in ambiente embedded. Gli sviluppatori embedded sono generali le uniche persone che utilizzano ambienti runtime personalizzate.

Il resto è spese generali per il sistema operativo che carica il file eseguibile. Non si ha intenzione di stesso molto lì a meno che non ci si sintonizza che a mano?

Utilizzando GCC, compilare il programma usando -Os piuttosto che uno degli altri flag di ottimizzazione (-O2 o -O3). Questo dice di ottimizzare per dimensione piuttosto che di velocità. Tra l'altro, a volte può rendere i programmi correre più veloce di ottimizzazioni di velocità avrebbe avuto, se qualche segmento critico succede ad adattarsi più bene. D'altra parte, -O3 può effettivamente indurre aumenti codice-size.

Ci potrebbero essere anche alcune bandiere linker dicendogli di lasciare fuori codice non utilizzato dal binario finale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top