Wenn ich ein Programm in eine einzelne Binärdatei kompilieren würde, eine Prüfsumme erstellen und diese dann auf demselben Computer mit denselben Compiler- und Compilereinstellungen erneut kompilieren und das neu kompilierte Programm mit einer Prüfsumme versehen würde, würde die Prüfsumme fehlschlagen?
Wenn ja, warum ist das so? Wenn nicht, würde eine andere CPU zu einer nicht identischen Binärdatei führen?
Antworten:
Kompilieren Sie dasselbe Programm mit denselben Einstellungen auf demselben Computer:
Obwohl die endgültige Antwort "es kommt darauf an" ist, ist zu erwarten, dass die meisten Compiler die meiste Zeit deterministisch sind und dass die erzeugten Binärdateien identisch sein sollten. In der Tat hängen einige Versionskontrollsysteme davon ab. Trotzdem gibt es immer Ausnahmen; es ist gut möglich, dass etwas Der Compiler wird irgendwo entscheiden, einen Zeitstempel oder einen solchen einzufügen (iirc, Delphi zum Beispiel). Oder der Build-Prozess selbst könnte dies tun. Ich habe Makefiles für C-Programme gesehen, die ein Präprozessor-Makro auf den aktuellen Zeitstempel setzen. (Ich denke, das würde jedoch als eine andere Compilereinstellung gelten.)
Beachten Sie auch, dass Sie, wenn Sie die Binärdatei statisch verknüpfen, den Status aller relevanten Bibliotheken auf Ihrem Computer effektiv einbinden. Jede Änderung in einer dieser Bibliotheken wirkt sich auch auf Ihre Binärdatei aus. Es sind also nicht nur die Compilereinstellungen relevant.
Kompilieren Sie dasselbe Programm auf einem anderen Rechner mit einer anderen CPU.
Hier sind alle Wetten aus. Die meisten modernen Compiler sind in der Lage, zielspezifische Optimierungen vorzunehmen. Wenn diese Option aktiviert ist, unterscheiden sich die Binärdateien wahrscheinlich, sofern die CPUs nicht ähnlich sind (und selbst dann ist dies möglich). Beachten Sie auch den obigen Hinweis zur statischen Verknüpfung: Die Konfigurationsumgebung geht weit über die Compilereinstellungen hinaus. Wenn Sie keine sehr strenge Konfigurationskontrolle haben, ist es sehr wahrscheinlich, dass sich etwas zwischen den beiden Computern unterscheidet.
quelle
gcc -c
kann durchaus identisch sein, aber die verknüpften Versionen unterscheiden sich. Auch ist es nicht nur-march
; Es gibt auch-mtune/-mcpu
und-mfpmatch
(und möglicherweise andere). Einige davon haben möglicherweise unterschiedliche Standardeinstellungen für verschiedene Installationen. Daher müssen Sie möglicherweise explizit den ungünstigsten Fall für Ihre Computer erzwingen. Dies kann die Leistung erheblich beeinträchtigen, insbesondere wenn Sie ohne sse auf i386 zurückgreifen. Und natürlich, wenn einer Ihrer CPUs ein ARM und der andere ein i686 ist ...Was Sie fragen, ist "ist die Ausgabe deterministisch Msgstr "Wenn Sie das Programm einmal kompiliert hätten, würden Sie es wahrscheinlich sofort wieder kompilieren. Wenn sich jedoch etwas ändert - auch eine kleine Änderung -, insbesondere in einer Komponente, die das kompilierte Programm verwendet, dann die Ausgabe des Compilers könnte sich auch ändern.
quelle
-frandom-seed=string
.Für alle Compiler? Nein, der C # -Compiler darf das zumindest nicht.
Eric Lippert hat Eine sehr gründliche Aufschlüsselung, warum die Ausgabe des Compilers nicht deterministisch ist .
Obwohl es spezifisch für eine Version des C # -Compilers ist, können viele Punkte im Artikel angewendet werden irgendein Compiler.
quelle
-frandom-seed=123
steuert einige GCC interne Zufälligkeit.man gcc
sagt:__FILE__
: Legen Sie die Quelle in einem festen Ordner ab (z./tmp/build
)__DATE__
,__TIME__
,__TIMESTAMP__
:-D
-Wdate-time
oder-Werror=date-time
: warnen oder scheitern, wenn entweder__TIME__
,__DATE__
oder__TIMESTAMP__
verwendet wird. Der Linux-Kernel 4.4 verwendet es standardmäßig.D
Fahne mitar
oder verwenden https://github.com/nh2/ar-timestamp-wiper/tree/master Briefmarken abwischen-fno-guess-branch-probability
: ältere manuelle Versionen sagen, es ist eine Quelle des Nichtdeterminismus, aber nicht länger . Ich bin nicht sicher, ob dies von abgedeckt wird-frandom-seed
oder nicht.Das Debian Reproduzierbares Bauprojekt Versuche, Debian-Pakete byteweise zu standardisieren, und bekamen kürzlich a Linux Foundation Zuschuss . Das beinhaltet mehr als nur das Zusammenstellen, aber es sollte von Interesse sein.
Baumwurzel hat ein
BR2_REPRODUCIBLE
Option, die einige Ideen auf Paketebene geben kann, aber an dieser Stelle noch lange nicht vollständig ist.Verwandte Themen:
quelle
Ich würde NEIN sagen, es ist nicht 100% deterministisch. Ich habe zuvor mit einer Version von GCC gearbeitet, die Ziel-Binärdateien für den Hitachi H8-Prozessor generiert.
Es ist kein Problem mit dem Zeitstempel. Selbst wenn das Problem mit dem Zeitstempel ignoriert wird, kann es aufgrund der spezifischen Prozessorarchitektur möglich sein, dass derselbe Befehl auf zwei leicht unterschiedliche Arten codiert wird, wobei einige Bits 1 oder 0 sein können. Meine bisherigen Erfahrungen zeigen, dass die generierten Binärdateien die meiste Zeit gleich waren aber gelegentlich erzeugte der gcc Binärdateien mit identischer Größe, aber einigen Bytes, die sich nur um 1 Bit unterschieden, z 0XE0 wird 0XE1.
quelle
Im Allgemeinen nicht. Die meisten einigermaßen ausgefeilten Compiler berücksichtigen die Kompilierzeit im Objektmodul. Selbst wenn Sie die Uhr zurücksetzen würden, müssten Sie hinsichtlich des Zeitpunkts, zu dem Sie die Kompilierung gestartet haben, sehr genau sein (und dann hoffen, dass die Datenträgerzugriffe usw. die gleiche Geschwindigkeit wie zuvor hatten).
quelle