Eu criei dois programas C
Programa 1
int main() { }
Programa 2
int main() { //Some Harmless comments }
AFAIK, ao compilar, o compilador (gcc) deve ignorar os comentários e espaços em branco redundantes e, portanto, a saída deve ser semelhante.
Mas quando verifiquei os md5sums dos binários de saída, eles não correspondem. Eu também tentei compilar com otimização -O3
e -Ofast
mas eles ainda não se encontraram.
O que esta acontecendo aqui?
EDITAR: os comandos exatos e md5sums são (t1.c é o programa 1 e t2.c é o programa 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
E sim, md5sums correspondem a várias compilações com os mesmos sinalizadores.
BTW, meu sistema é gcc (GCC) 5.2.0
eLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux
c
gcc
optimization
binary-reproducibility
Usuário Registrado
fonte
fonte
Respostas:
É porque os nomes dos arquivos são diferentes (embora a saída das strings seja a mesma). Se você tentar modificar o próprio arquivo (em vez de ter dois arquivos), notará que os binários de saída não são mais diferentes. Como Jens e eu dissemos, é porque o GCC despeja uma carga inteira de metadados nos binários que cria, incluindo o nome de arquivo de origem exato (e AFAICS também clang).
Experimente isto:
Isso explica porque seus md5sums não mudam entre as compilações, mas são diferentes entre os diferentes arquivos. Se quiser, você pode fazer o que Jens sugeriu e comparar a saída de
strings
cada binário, você notará que os nomes dos arquivos estão embutidos no binário. Se você quiser "consertar" isso, você podestrip
os binários e os metadados serão removidos:fonte
O motivo mais comum são nomes de arquivos e carimbos de data / hora adicionados pelo compilador (geralmente na parte de informações de depuração das seções ELF).
Tente correr
e você pode ver o motivo. Certa vez, usei isso para descobrir por que a mesma fonte causaria código diferente quando compilada em diretórios diferentes. A descoberta foi que o
__FILE__
macro se expandiu para um nome de arquivo absoluto , diferente nas duas árvores.fonte
Nota : lembre-se de que o nome do arquivo de origem vai para o binário não compactado, portanto, dois programas provenientes de arquivos de origem com nomes diferentes terão hashes diferentes.
Em situações semelhantes, caso o acima não se aplique , você pode tentar:
strip
contra o binário para remover um pouco de gordura. Se os binários removidos são os mesmos, então alguns metadados não são essenciais para a operação do programa.strings
ou despeje ambos os programas em hexadecimal e execute um diff nos dois despejos hexadecimais. Depois de localizar a (s) diferença (ões), você pode tentar ver se há alguma rima ou razão para elas (PID, timestamps, timestamp do arquivo de origem ...). Por exemplo, você pode ter uma rotina armazenando o carimbo de data / hora no momento da compilação para fins de diagnóstico.fonte
gcc (GCC) 5.2.0
eLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux