広域変数が配置されるセクション

※この実験は、以下の環境で実施しました。

$ gcc -v
gcc バージョン 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)

$ as -V
GNU アセンブラ バージョン 2.23.2 (i686-linux-gnu)、BFD バージョン (GNU Binutils for Ubuntu) 2.23.2 を使用

$ ld -v
GNU ld (GNU Binutils for Ubuntu) 2.23.2

以下で場合分けをした広域変数を定義します。

1.初期値あり/なし
2.初期値=0またはNULL/0以外またはNULL以外
3.1と2について、const指定あり/なし
int n_void;
int n_zero = 0;
int n_notzero = 1;
char *p_void;
char *p_null = NULL;
char *p_notnull = "This is pointer.";
const int cn_void;
const int cn_zero = 0;
const int cn_notzero = 1;
char * const cp_void;
char * const cp_null = NULL;
char * const cp_notnull = "This is pointer.";

上記のプログラムについて、シンボルテーブルをダンプすると、

$ nm pointer
(中略)
080484a8 R cn_notzero
0804a038 B cn_void
080484a4 R cn_zero
(中略)
080484b0 R cp_notnull
080484ac R cp_null
0804a03c B cp_void
(中略)
0804a01c D n_notzero
0804a030 B n_void
0804a028 B n_zero
0804a020 D p_notnull
0804a02c B p_null
0804a034 B p_void

まとめると、以下となりました。

初期値 const指定 配置先セクション
なし なし .bss
なし const .bss
0 or NULL なし .bss
0 or NULL const .rodata
上記以外 なし .data
上記以外 const .rodata

つまり、以下の評価順で、配置先セクションが決定される…ということのようです。

評価順 条件 配置先セクション
1 初期値なし .bss
2 const指定あり .rodata
3 初期値=0またはNULL .bss
4 初期値が上記以外 .data

ヒューリスティック(大雑把)に表現すると、

・初期値の無い変数は、.bssセクションに配置される。
・初期値の無いconst指定は無視される。
・初期値のあるconst定数は、初期値の内容とは無関係に、.rodataセクションに配置される。
・初期値のある変数は、
  初期値=0またはNULL →初期値なしと同じ扱い。
  上記以外      →.dataセクションに配置される。