質問
そのセグメント.BSS,.データその他)の実行可能ファイルの静的変数に格納されるような名前衝突?例えば:
foo.c: bar.c:
static int foo = 1; static int foo = 10;
void fooTest() { void barTest() {
static int bar = 2; static int bar = 20;
foo++; foo++;
bar++; bar++;
printf("%d,%d", foo, bar); printf("%d, %d", foo, bar);
} }
まコンパイルの両方のファイルにリンクさせることで主るfooTest()およびbarTest繰り返し、printf算値。う意味があるので、fooとbarの変数は現地の翻訳ます。
ものに保管配?
ている場合がありますことを想定するツールチェーンが出力ファイルをELF形式です。このことから、 信じる ることが は する一部のスペースの貸し出しの実行ファイル用の静的変数です。
議論の目的能としてのGCCのツールチェーン.
解決
お統計行に依存してい ゼロの初期化 います。 ゼロの初期化 静的データがありますので、 .BSS(ブロックの開始によるシンボル), 不 ゼロの初期化 データの入っていた .データ
他のヒント
プログラムが読み込み、組織の異なるセグメント一つのセグメント データセグメント.データセグメントは、さらにサブパ
初期化されたデータセグメント: すべてのグローバル静的および定データが格納されています。
初期化されていないデータセグメント(BSS): すべての初期化されていないデータが格納されこのセグメント
ここでは、図の説明このコンセプト:
こちらは非常に良いリンクを説明するこれらのコンセプト
実際、変数のタプル(貯蔵、範囲、種類、住所、値):
storage : where is it stored, for example data, stack, heap...
scope : who can see us, for example global, local...
type : what is our type, for example int, int*...
address : where are we located
value : what is our value
地域の範囲が地元の並進ユニット(ソースファイル)は、機能ブロックの場所により、定義されています。を可変に見える以上の機能、それは間違いなくいずれかである必要がありいずれかのデータまたはBSS域かどうかに応じて、その明示的に初期化されない。そのscopedそこから全ての機能(s)や機能(s)内のソースファイルです。
の保存場所のデータを実装に依存します。
しかし、その意味 静的 は"内部連携".これにより、シンボル 内部 の作成ユニット(foo.c,バーがあります。c)には参照できません外を作成ユニットです。りすることはできない名前の衝突.
とは思っていないが衝突.静的にファイルレベル(外部機能の変数として地域の現在の編集部(ファイル).なんてことはありません見える以外に現在のファイルになっています。
静的内部の機能が異なる変数は、関数をかけて食べるという習慣があり、その値は全体を通して保持され話する機能です。
有効な、静的は異なるものであるとの考え方によって同じ場所に設置します。にoth場合ただし、制限されている視認性の変動防止の名前空間衝突で
とはいえ、そのことは両輪で進めていくことに格納されるデータが初期化されています。のBSSもたちのためのバイト-セット-<something> 開催される変数ではないのに初期化されます。
どのようなデータベースで objdump -Sr
実際に理解しようを理解しなければならなリンカー移動等の円滑化の促進ことがなければ、今回の触れることが考えら これらの最初.
ようにして解析Linux x86-64ELF例を見なし:
#include <stdio.h>
int f() {
static int i = 1;
i++;
return i;
}
int main() {
printf("%d\n", f());
printf("%d\n", f());
return 0;
}
コンパイル:
gcc -ggdb -c main.c
ンジニアリング、逆アセンブル、コード:
objdump -Sr main.o
-S
decompilesのコードのオリジナルソースが混在-r
を示して情報移転
内decompilationの f
い:
static int i = 1;
i++;
4: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # a <f+0xa>
6: R_X86_64_PC32 .data-0x4
の .data-0x4
することが最初のバイトの .data
セグメント
の -0x4
があるので使っていRIPは相対で、この %rip
の指導- R_X86_64_PC32
.
が必要ですのでRIPを 以下の 指導を開始する4バイトの後に 00 00 00 00
では何を得移転を行います。についてご説明してこの詳細: https://stackoverflow.com/a/30515926/895245
そして、このソース i = 1
て同様の解析を行っている:
static int i = 0
く.bss
static int i = 1
く.data
により、プラットフォームやコンパイラがいます。一部のコンパイラの店舗に直接コードセグメント静的変数は、常にのみアクセスの現在の翻訳単位の名称はこのように輸出された理由は名前の衝突なが発生します。
データ宣言された集大成単位のうちきます。BSSはます。データのファイルを出力します。InitialisedデータBSS,uninitalisedます。
の違いを静的およびグローバルデータ付きのシンボル情報をファイルです。コンパイラが含まのシンボル情報だけのグローバル情報など。
リンカーを尊重し、この情報です。シンボル情報を静的変数には破棄または難号化したように静的変数で参照されるもの(またはデバッグシンボルごすことができました。でない場合での集計単位が影響を受けてのリンカー解決のローカル参照です。
静的変数に格納データセグメントまたはコードセグメントしています。
を確認することができませんので、あらかを割り当てスタックやヒープ.
ありませんリスクの衝突で static
キーワードの定義の範囲の変数をファイルまたは機能の衝突があり、コンパイラ/リンカーに警告するようです。
素敵な 例
でもこの問題は少し古いが、誰もいないポイントは有益な情報:チェックによmohit12379'を説明する店舗の静的変数と同じ名前のシンボルテーブル:http://www.geekinterview.com/question_details/24745
んでobjdump、gdb、こちらのは、何を取得します:
(gdb) disas fooTest
Dump of assembler code for function fooTest:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: mov 0x200b09(%rip),%eax # 0x601040 <foo>
0x0000000000400537 <+10>: add $0x1,%eax
0x000000000040053a <+13>: mov %eax,0x200b00(%rip) # 0x601040 <foo>
0x0000000000400540 <+19>: mov 0x200afe(%rip),%eax # 0x601044 <bar.2180>
0x0000000000400546 <+25>: add $0x1,%eax
0x0000000000400549 <+28>: mov %eax,0x200af5(%rip) # 0x601044 <bar.2180>
0x000000000040054f <+34>: mov 0x200aef(%rip),%edx # 0x601044 <bar.2180>
0x0000000000400555 <+40>: mov 0x200ae5(%rip),%eax # 0x601040 <foo>
0x000000000040055b <+46>: mov %eax,%esi
0x000000000040055d <+48>: mov $0x400654,%edi
0x0000000000400562 <+53>: mov $0x0,%eax
0x0000000000400567 <+58>: callq 0x400410 <printf@plt>
0x000000000040056c <+63>: pop %rbp
0x000000000040056d <+64>: retq
End of assembler dump.
(gdb) disas barTest
Dump of assembler code for function barTest:
0x000000000040056e <+0>: push %rbp
0x000000000040056f <+1>: mov %rsp,%rbp
0x0000000000400572 <+4>: mov 0x200ad0(%rip),%eax # 0x601048 <foo>
0x0000000000400578 <+10>: add $0x1,%eax
0x000000000040057b <+13>: mov %eax,0x200ac7(%rip) # 0x601048 <foo>
0x0000000000400581 <+19>: mov 0x200ac5(%rip),%eax # 0x60104c <bar.2180>
0x0000000000400587 <+25>: add $0x1,%eax
0x000000000040058a <+28>: mov %eax,0x200abc(%rip) # 0x60104c <bar.2180>
0x0000000000400590 <+34>: mov 0x200ab6(%rip),%edx # 0x60104c <bar.2180>
0x0000000000400596 <+40>: mov 0x200aac(%rip),%eax # 0x601048 <foo>
0x000000000040059c <+46>: mov %eax,%esi
0x000000000040059e <+48>: mov $0x40065c,%edi
0x00000000004005a3 <+53>: mov $0x0,%eax
0x00000000004005a8 <+58>: callq 0x400410 <printf@plt>
0x00000000004005ad <+63>: pop %rbp
0x00000000004005ae <+64>: retq
End of assembler dump.
こちらはobjdump結果
Disassembly of section .data:
0000000000601030 <__data_start>:
...
0000000000601038 <__dso_handle>:
...
0000000000601040 <foo>:
601040: 01 00 add %eax,(%rax)
...
0000000000601044 <bar.2180>:
601044: 02 00 add (%rax),%al
...
0000000000601048 <foo>:
601048: 0a 00 or (%rax),%al
...
000000000060104c <bar.2180>:
60104c: 14 00 adc $0x0,%al
ということは、その言は、四つの変数内データセクションイベントに同じ名前が異なるオフセットされます。
の答えをもつことになるかもしれないのコンパイラなのかも知れません。を編集したいご質問ご注意いただきたいものという概念セグメントのない存ISO CやISO C++).たとえば、Windowsで実行可能な行シンボル名です。One'foo'がオフセット0x100、その他のも0x2B0、コードの両面から翻訳単位の集約された知る-オフセット"の"foo.
うに変更され、独立して、しばしたいということではないかと思われ他の開発するために包むだけで、あっという間に名前空間
りますが、既にご存知のいずれかで店bss(ブロックの開始記号と呼ばれる初期化されていないデータセグメントまたは初期化されたデータセグメント
き、簡単な例
void main(void)
{
static int i;
}
上記の静的変数が初期化されませんように初期化されていないデータセグメント(bss).
void main(void)
{
static int i=10;
}
もちろんで初期化される10のように初期化されたデータセグメント