Я создал две программы на C
Программа 1
int main() { }
Программа 2
int main() { //Some Harmless comments }
AFAIK, при компиляции компилятор (gcc) должен игнорировать комментарии и избыточные пробелы, и, следовательно, вывод должен быть аналогичным.
Но когда я проверил md5-суммы выходных двоичных файлов, они не совпадают. Я также попытался компиляции с оптимизацией -O3
и , -Ofast
но они по- прежнему не совпадают.
Что здесь происходит?
РЕДАКТИРОВАТЬ: точные команды и md5sums (t1.c - это программа 1, а t2.c - программа 2)
gcc ./t1.c -o aaa
gcc ./t2.c -o bbb
98c1a86e593fd0181383662e68bac22f aaa
c10293cbe6031b13dc6244d01b4d2793 bbb
gcc ./t2.c -Ofast -o bbb
gcc ./t1.c -Ofast -o aaa
2f65a6d5bc9bf1351bdd6919a766fa10 aaa
c0bee139c47183ce62e10c3dbc13c614 bbb
gcc ./t1.c -O3 -o aaa
gcc ./t2.c -O3 -o bbb
564a39d982710b0070bb9349bfc0e2cd aaa
ad89b15e73b26e32026fd0f1dc152cd2 bbb
И да, md5sums совпадают в нескольких компиляциях с одинаковыми флагами.
Кстати, моя система gcc (GCC) 5.2.0
иLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux
c
gcc
optimization
binary-reproducibility
зарегистрированный пользователь
источник
источник
Ответы:
Это потому, что имена файлов разные (хотя вывод строк одинаковый). Если вы попытаетесь изменить сам файл (вместо того, чтобы иметь два файла), вы заметите, что выходные двоичные файлы больше не отличаются. Как и Йенс, и я сказали, это потому, что GCC выгружает целую загрузку метаданных в бинарные файлы, которые он строит, включая точное имя исходного файла (и AFAICS так же звенит).
Попробуй это:
Это объясняет, почему ваши md5sums не меняются между сборками, но они различны для разных файлов. Если вы хотите, вы можете сделать то, что предложил Йенс, и сравнить вывод
strings
для каждого двоичного файла, вы заметите, что имена файлов встроены в двоичный файл. Если вы хотите «исправить» это, вы можетеstrip
удалить двоичные файлы и метаданные:источник
Наиболее частая причина - это имена файлов и отметки времени, добавленные компилятором (обычно в части отладочной информации в разделах ELF).
Попробуйте бежать
и вы можете увидеть причину. Однажды я использовал это, чтобы понять, почему один и тот же источник вызывает разный код при компиляции в разных каталогах. Обнаружено, что
__FILE__
макрос расширяется до абсолютного имени файла, различающегося в обоих деревьях.источник
Примечание : помните, что имя исходного файла входит в распакованный двоичный файл, поэтому две программы, поступающие из исходных файлов с разными именами, будут иметь разные хэши.
В аналогичных ситуациях, если вышеперечисленное не применимо , вы можете попробовать:
strip
с двоичным файлом, чтобы удалить немного жира. Если вырезанные двоичные файлы одинаковы, значит, это были некоторые метаданные, которые не важны для работы программы.strings
или выгрузите обе программы в шестнадцатеричный формат и выполните сравнение двух шестнадцатеричных дампа. Обнаружив разницу (я), вы можете попытаться увидеть, есть ли для них какая-то рифма или причина (PID, временные метки, временная метка исходного файла ...). Например, у вас может быть процедура хранения метки времени во время компиляции для диагностических целей.источник
gcc (GCC) 5.2.0
иLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux