112

2 つの C プログラムを作成しました

  1. プログラム 1

    int main()
    {
    }
    
  2. プログラム 2

    int main()
    {
    //Some Harmless comments
    }
    

私の知る限り、コンパイル時に、コンパイラ(gcc)はコメントと冗長な空白を無視する必要があるため、出力は類似している必要があります。

しかし、出力バイナリの md5sums を確認すると、一致しません。最適化してコンパイルも試みまし-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.0Linux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux

4

3 に答える 3

160

これは、ファイル名が異なるためです (出力される文字列は同じですが)。(2 つのファイルではなく) ファイル自体を変更してみると、出力バイナリに違いがないことがわかります。Jens と私が言ったように、それは GCC が、正確なソース ファイル名を含めて、ビルドするバイナリにメタデータの全負荷をダンプするためです(そして AFAICS も同様に clang を行います)。

これを試して:

$ cp code.c code2.c subdir/code.c
$ gcc code.c -o a
$ gcc code2.c -o b
$ gcc subdir/code.c -o a2
$ diff a b
Binary files a and b differ
$ diff a2 b
Binary files a2 and b differ
$ diff -s a a2
Files a and a2 are identical

これは、ビルド間で md5sums が変わらない理由を説明していますが、異なるファイル間では異なります。必要に応じて、Jens が提案したことを実行しstrings、各バイナリの出力を比較して、ファイル名がバイナリに埋め込まれていることに気付くことができます。これを「修正」したい場合はstrip、バイナリとメタデータを削除できます。

$ strip a a2 b
$ diff -s a b
Files a and b are identical
$ diff -s a2 b
Files a2 and b are identical
$ diff -s a a2
Files a and a2 are identical
于 2015-09-04T15:10:05.353 に答える
16

:ソース ファイル名はストリップされていないバイナリに含まれるため、異なる名前のソース ファイルからの 2 つのプログラムは異なるハッシュを持つことに注意してください。

同様の状況で、上記が当てはまらない場合は、次を試すことができます。

  • stripバイナリに対して実行して、一部の脂肪を削除します。削除されたバイナリが同じである場合、それはプログラムの操作に不可欠ではないメタデータです。
  • アセンブリの中間出力を生成して、違いが実際の CPU 命令にないことを確認します (または、違いが実際にどこにあるかをより正確に特定するため)
  • を使用するstringsか、両方のプログラムを 16 進数にダンプし、2 つの 16 進数ダンプで diff を実行します。違いを見つけたら、韻や理由 (PID、タイムスタンプ、ソース ファイルのタイムスタンプなど) があるかどうかを確認してみてください。たとえば、診断目的でコンパイル時にタイムスタンプを格納するルーチンがあるとします。
于 2015-09-04T15:07:43.797 に答える