3

こんにちは Linux マシン (64 ビット) で gcc を使用してコンパイルされた以下のコード スニペットと、対応するメモリ マップを検討してください。

#include <stdio.h>

int global = 2;

int main(void)
{
    int local = 0;

    return 0;
}

text       data     bss     dec     hex filename

1092        500      16    1608     648 mem

ここには 2 に初期化されたグローバル変数があるためです。データセグメントに格納されている 以下のように const にする場合を考える

#include <stdio.h>

int const global = 2;

int main(void)
{
    int local = 0;

    return 0;
}

text       data     bss     dec     hex filename
1096        496      16    1608     648 mem

ここでは、グローバル変数がデータ セグメントからテキスト セグメントに移動されます。

データからテキスト セグメントに移動したのはなぜですか?

データセグメントはリードエリアとリードライトエリアに分かれているので、データのリードエリアに格納されているはずですよね?

コードの途中で初期化された初期化されていないグローバル変数はどうなりますか?

4

3 に答える 3

12

最新のシステムでは、定数読み取り専用データ用に予約されたオブジェクトファイルのセクションにあります。そのセクションは、デフォルトモードのコマンドによって「テキスト」(プログラムコード)セクションと一緒にまとめられsizeますが、より詳細な情報を提供することができます。

$ size test.o  # compiled from the code in the question
   text    data     bss     dec     hex filename
     58       0       0      58      3a test.o

$ size -A test.o
test.o  :
section           size   addr
.text                6      0
.data                0      0
.bss                 0      0
.rodata              4      0
.comment            29      0
.note.GNU-stack      0      0
.eh_frame           48      0
Total               87

最初のコマンドで生成された「テキスト」の数値が、2番目の質問で生成された、、、および数値の合計であることがわかり.textます.rodata.eh_frame

次のコマンドで.rodataはなく、定数が含まれていることがわかります。.textobjdump

$ objdump -t test.o | grep -w global
0000000000000000 g     O .rodata    0000000000000004 global

(「g」はグローバルを表し、「O」は「オブジェクト」を表し、「F」は関数を表します。)

于 2012-10-20T23:33:08.073 に答える
2

テキスト セグメントは読み取り専用であるため、定数をテキスト セグメントに配置することで、コンパイラはそれが真の定数であることを保証します。他のオブジェクトファイルにアクセスできると宣言されているため、どこかに保存する必要があります。したがって、選択肢はデータセグメントとテキストセグメントです。

静的変数の場合、定数であるかどうかに関係なく、使用されていないため、コンパイラはそれを削除できる可能性があります。静的で定数の場合、コンパイラは、生成するコードでその値を使用することを優先して、それを削除する可能性があります。

于 2012-10-20T23:17:28.557 に答える
0

以前の編集に戻ります。定数を変更できないため、定数をデータセグメントにまったく格納しないようにコンパイラを最適化するだけで、決して変更できないと思います。

于 2012-10-20T23:03:43.863 に答える