2

次のプログラムがあるとします。

unsigned char g1[] = { 0x1a, 0x2a, 0x3a, 0x4a };
static unsigned char g2[] = { 0x1b, 0x2b, 0x3b, 0x4b };

int main()
{
  unsigned char l1[] = { 0x1c, 0x2c, 0x3c, 0x4c };
  static unsigned char l2[] = { 0x1d, 0x2d, 0x3d, 0x4d };
}

その後、「g++ test.cpp -o test」と単純にコンパイルし、バイナリで hexdump -C を実行した後、g1、g2、および l2 のシーケンスがバイナリで明確に見つかることに気付きました。l1 (1c 2c 3c 4c) のシーケンスのみが、明らかにバイナリ ファイルのどこにも存在しません。

それがなぜなのか、誰にもわかりますか?

4

3 に答える 3

4

その関数呼び出しのスタックに割り当てられているためです。通常、このような場合、次の2つのいずれかが発生します。

  1. コンパイラそのシーケンスをデータセクションに格納し、基本的にそれをスタックバッファにmemcpyします。

  2. コンパイラは基本的に「move」命令をハードコーディングして、命令セットの最大の即値(多くの場合4バイト整数)からシーケンスを再アセンブルします。

前述の「巻き戻し」のように最適化されていない場合は、おそらく#2が発生しています。逆アセンブルを見ると、プロプログラム(または事前にアセンブルされたasmコード)の方がわかりやすくなります。-S.sファイルを使用 して確認します。

于 2013-01-16T13:36:48.450 に答える
3

私の推測では、それは非static自動 (非グローバル) であるため、誰も外部から参照できないことを知るのは簡単です。未使用ですので、お譲り可能です。

于 2013-01-16T13:34:33.637 に答える
0

l1[]l2[]はコンパイラの最適化中に削除されます。これは、両方が存在するためですlocal and unused variables(両方の変数が他の場所で使用される可能性はありません)。

-Sアセンブリ コードを生成するオプションを使用 l1[]してコードをコンパイルできますl2[]

入力ファイルは、アセンブリ ファイルを生成するx.cコマンドでコンパイルされましたgcc -S x.cx.s

main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $16, %esp
    movb    $28, -4(%ebp)
    movb    $44, -3(%ebp)
    movb    $60, -2(%ebp)
    movb    $76, -1(%ebp)
    leave
    ret
    .size   main, .-main
    .data
    .type   l2.1250, @object
    .size   l2.1250, 4

しかし、 の定義を見つけることができますg1[] and g2[]

    .file   "x.c"
.globl g1
    .data
    .type   g1, @object
    .size   g1, 4
g1:
    .byte   26
    .byte   42
    .byte   58
    .byte   74
    .type   g2, @object
    .size   g2, 4
g2:
    .byte   27
    .byte   43
    .byte   59
    .byte   75
    .text
.globl main
    .type   main, @function  

さらに、フラグ-O3 最適化フラグ レベル 3を使用してコードをコンパイルすると、 の定義のみg1[]が存在することを知っておくと興味深いでしょう。グローバル静的変数 (ファイルに対してプライベート) も削除されます。

入力ファイルは、アセンブリ ファイルを生成するx.cコマンドでコンパイルされましたgcc -S -O3 x.cx.s

下:

    .file   "x.c"
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    popl    %ebp
    ret
    .size   main, .-main
.globl g1
    .data
    .type   g1, @object
    .size   g1, 4
g1:
    .byte   26
    .byte   42
    .byte   58
    .byte   74
    .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
    .section    .note.GNU-stack,"",@progbits  

g1[]はグローバル データのみ存在し、g2[]で削除され-O3ます。

g2[]use defined static unsigned char g2[]so はこのファイル内でのみアクセスし、使用しないでください。ただしg1[]、グローバルなので、他のファイルにこれが含まれていると、他のプログラムで役立つ場合があります。また、コンパイラはグローバル オブジェクトを最適化することはできません。

参照: 「未使用」のグローバル変数がコンパイルされないようにするにはどうすればよいですか?

つまり、これはすべてコンパイラの最適化によるものです。

于 2013-01-16T13:46:06.153 に答える