L'output gcc del file oggetto (linguaggio C) varia tra le compilation? Non ci sono informazioni specifiche sul tempo, nessuna modifica nelle opzioni di compilazione o il codice sorgente. Nessuna modifica nelle librerie collegate, né variabili ambientali. Questo è un crosscompiler VSSWorks MIPS64, se questo aiuta. Personalmente penso che non dovrebbe cambiare. Ma osservo che a volte casualmente le istruzioni hanno generato dei cambiamenti. Non so qual è la ragione. Qualcuno può far luce su questo?I file oggetto prodotti da gcc possono variare tra compilazioni della stessa sorgente con le stesse opzioni?
risposta
Perché dovrebbe variare? È sempre lo stesso risultato. Prova questo:
for i in `seq 1000`; do gcc 1.c; md5sum a.out; done | sort | uniq | wc -l
La risposta è sempre 1
. Sostituire 1.c
e a.out
in base alle proprie esigenze.
Quanto sopra conta quanti diversi eseguibili vengono generati da gcc
durante la compilazione della stessa origine per 1000
volte.
Provare cosa? Puoi per favore elaborare? –
Spiacente, inviato troppo presto :( –
ok, ho provato cose del genere.La nostra ipotesi che non dovrebbe cambiare in realtà sembra essere vera, ma per un codice di grandi dimensioni, lo stesso vale per il compilatore. set di istruzioni alla compilation 'c1' e successivamente genera un output diverso per la compilation 'c2' mantenendo la stessa funzionalità? –
Come viene costruito? Ad esempio, se ho creato lo stesso kernel di Linux, include un contatore che viene incrementato ogni build. GCC ha opzioni per utilizzare le informazioni del profiler per guidare la generazione del codice, se le informazioni di profilazione cambiano, così sarà il codice.
Che cosa hai analizzato? L'assembly generato, un objectdump di file oggetto o l'eseguibile? Come hai confrontato le diverse versioni? Sei sicuro hai guardato il codice eseguibile, non i timestamp del compilatore/assemblatore/linker?
Qualcosa è cambiato nell'ambiente? Nuove librerie (e file header/dichiarazioni/definizioni macro!)? Nuovo compilatore, linker? Nuovo kernel (sì, alcuni file header provengono dal sorgente del kernel e vengono forniti con esso)?
Eventuali modifiche alle variabili di ambiente (un altro utente che esegue la compilazione, una macchina diversa, un collegamento diverso alla rete fornisce un indirizzo IP diverso che fa parte della build)?
Vorrei provare a tracciare il processo di compilazione in dettaglio (eseguire una compilazione e acquisire l'output in un file, e farlo di nuovo, confrontare quelli).
Completamente disorientato ...
"Come è costruito? Ad esempio, se ho costruito lo stesso kernel di Linux, include un contatore che viene incrementato ogni build.GCC ha opzioni per usare le informazioni del profiler per guidare la generazione del codice, se le informazioni di profilazione cambiano, così sarà codice." -> Nessuna informazione profilo/debug; -O2 abilitato. –
"Che cosa hai analizzato?" -> generato l'objdump e confrontato. La differenza era nelle istruzioni di una macchina in una funzione. Sto solo compilando una libreria statica, quindi nessun eseguibile ... Ho analizzato la libreria statica. Ignorerei i timestamp se fosse così. La differenza erano chiaramente le istruzioni della macchina. Nessun cambiamento ambientale. Nel mio caso d'uso, è impensabile cambiare i kernel tra due compilation. Non c'è una tale necessità. Sto costruendo una libreria per un sistema embedded attraverso un cross-compilatore. Ho anche provato a confrontare il log di costruzione. Non c'è differenza. –
@arun, erano quelle le uniche differenze? Molto, molto strano. – vonbrand
Ho avuto un problema simile con g ++. Le versioni precedenti alla 4.3 hanno prodotto esattamente gli stessi file oggetto ogni volta. Con 4.3 (e successivi?) Alcuni dei nomi dei simboli mutilati sono diversi per ogni esecuzione, anche senza -g o altre registrazioni. Forse usare un timestamp o un numero casuale (spero di no). Ovviamente alcuni di questi simboli lo trasformano nel tavolo dei simboli .o e ottieni una differenza. Eliminare i file oggetto li rende uguali di nuovo (confronto binario negativo). g ++ -c file.C; strip file.o; cmp file.o origfile.o
Il mio gcc a volte produce codice diverso esattamente per lo stesso ingresso. I file oggetto di output differiscono esattamente in un byte.
A volte ciò causa errori del linker, poiché un possibile file oggetto non è valido. La ricompilazione di un'altra versione di solito corregge l'errore del linker.
La versione di gcc è la 4.3.4 su Suse Linux Enterprise. I parametri gcc sono:
cc -std=c++0x -Wall -fno-builtin -march=native -g -I<path1> -I<path2> -I<path3> -o obj/file.o -c file.cpp
Se qualcuno sperimenta lo stesso effetto, allora per favore fatemelo sapere.
Ho trovato che in almeno alcuni ambienti, la stessa fonte può produrre un eseguibile diverso se l'albero dei sorgenti per la build successiva si trova in una directory diversa. Esempio:
Verificare una copia pristine del progetto in dir1. Fai una ricostruzione completa da zero.
Quindi, con lo stesso utente sulla stessa macchina, eseguire la stessa copia esatta del codice sorgente in dir2 (dir1! = Dir2). Esegui un'altra ricostruzione completa da zero.
Queste build sono a pochi minuti di distanza, senza modifiche alla toolchain o alle librerie o codici di terze parti. Il confronto binario del codice sorgente è lo stesso. Tuttavia, l'eseguibile in dir1 ha diversi md5sum rispetto all'eseguibile in dir2.
Se si confrontano i diversi eseguibili nell'editor hex di BeyondCompare, la differenza non è solo una piccola sezione che potrebbe essere plausibilmente un timestamp.
I do ottenere lo stesso eseguibile se si crea in dir1, quindi ricompilare nuovamente in dir1. Lo stesso se continuo a costruire la stessa fonte più e più volte da dir2.
La mia unica ipotesi è che alcuni tipi di percorsi assoluti della gerarchia include siano incorporati nell'eseguibile.
Si prega di elaborare: Il codice sorgente è sempre lo stesso? Cambiano le altre librerie collegate? Le informazioni specifiche del tempo si fanno strada nella fonte (come il tempo di compilazione o un numero di revisione VCS)? Potresti pubblicare un esempio in grado di riprodurre il problema? –
Sei sicuro che le modifiche siano in istruzioni valide valide? È possibile che alcune sezioni contengano bit non inizializzati, forse perché GCC "sa" che quei bit non contano. Lo stato dei bit non inizializzati può naturalmente variare casualmente tra le esecuzioni dello stesso programma, sullo stesso input. – unwind
@MichaelFoukarakis: No, nessun timestamp nel codice. Le librerie rimangono le stesse. Già menzionato nel titolo quella fonte non cambia. –