2

関数 から始めたとしましょうfoo()。これは正しいですが、スタイルが不十分です。

int foo(void)
{
    // Some comment
    int b;
    int    a;

    getAandB(&a, &b);

    return a+b;
}

機能を変更せずに、このコード ブロックを再フォーマットしたい:

int foo(void)
{
    // A more descriptive comment
    int a, b;

    getAandB(&a, &b);

    return a + b;
}

これら 2 つのブロックが機能的に同等であることを示すために使用できるツールはありますか? コード ベース全体を再構築するオプションはなく、このコード ブロックだけを個別にテストしたいとします。getAandB()は別の場所で定義されているため、リンクできません。

この場合、ツールの組み合わせを使用して機能的同等性を証明することは可能ですか?

4

5 に答える 5

0

生成されたアセンブリのアプローチをチェックしたい場合は、次の方法で実行できます。

私はあなたの2つの関数が2つのファイルに入れられていると仮定していa.cますb.c:

$ gcc -O0 -S a.c
$ gcc -O0 -S b.c
$ diff a.s b.s
1c1
<  .file "a.c"
---
>  .file "b.c"
13,14c13,14
<  leaq -4(%rbp), %rsi
<  leaq -8(%rbp), %rdi
---
>  leaq -8(%rbp), %rsi
>  leaq -4(%rbp), %rdi
17,18c17,18
<  movl -8(%rbp), %edx
<  movl -4(%rbp), %eax
---
>  movl -4(%rbp), %edx
>  movl -8(%rbp), %eax
$ 

アーティファクトが最適化されないように、最適化 (-O0) をオフにします。

したがって、驚くべきことに、gcc (4.1.2) の出力は、これら 2 つの関数でわずかに異なります。しかし、これを少し注意深く見ると、理由がわかります。最初の関数でbは is beforeが宣言されているaため、スタックのbaにありますが、2 番目の関数では逆になっています。

したがって、スワップするab、生成されたアセンブリが実際には同一であることがわかります。

$ gcc -O0 -S b1.c
$ diff a.s b1.s
1c1
<  .file "a.c"
---
>  .file "b1.c"
$ 

または、生成されたアセンブリが実際に何であるかではなく、生成されたアセンブリが異なるかどうかのみを気にする場合は、これをすべて 1 つの派手な bash コマンドで行うことができます。

$ diff --brief <(cat a.c | gcc -O0 -S -xc - -o-) <(cat b.c | gcc -O0 -S -xc - -o-)
Files /dev/fd/63 and /dev/fd/62 differ
$ echo $?
1
$ diff --brief <(cat a.c | gcc -O0 -S -xc - -o-) <(cat b1.c | gcc -O0 -S -xc - -o-)
$ echo $?
0
$ 
于 2013-10-17T16:37:36.783 に答える