[解決済み] コンパイル時にメモリを確保する」の本当の意味とは?
質問
C言語やC++などのプログラミング言語では、静的メモリ割り当てと動的メモリ割り当てについてよく言及されます。その概念は理解できるのですが、「すべてのメモリはコンパイル時に割り当てられた(予約された)」という表現にはいつも困惑させられます。
コンパイルは、私の理解では、高レベルのC/C++コードを機械語に変換し、実行ファイルを出力するものです。コンパイルされたファイルでは、メモリはどのように確保されるのでしょうか?メモリは常に仮想メモリ管理されたRAMに割り当てられるのではありませんか?
メモリ確保は、定義上、実行時の概念ではないのですか?
C/C++のコードで1KBの静的割り当て変数を作ったら、実行ファイルのサイズも同じだけ大きくなるのでしょうか?
これは、"Static allocation"という見出しで、このフレーズが使われているページの一つです。
バック・トゥ・ベーシックス メモリ割り当て、その歴史をたどる
どのように解決する?
コンパイル時に割り当てられるメモリとは、コンパイラがコンパイル時に、プロセスのメモリマップ内で特定のものをどこに割り当てるかを決定することを意味します。
例えば、グローバル配列について考えてみましょう。
int array[100];
コンパイラは,コンパイル時に配列の大きさを知っており,その大きさに応じて
int
そのため、コンパイル時に配列の全サイズを知ることができます。また、グローバル変数はデフォルトで静的記憶期間を持ちます。プロセスのメモリ空間(.data/.bssセクション)の静的メモリ領域に割り当てられているのです。この情報を元に
コンパイラはコンパイル時に、その静的メモリ領域のどのアドレスに配列を配置するかを決定します。
.
もちろん、メモリアドレスは仮想アドレスです。プログラムは自分自身のメモリ空間全体(例えば0x00000000から0xFFFFFFFまで)を持っていると仮定しています。そのため、コンパイラは、「よし、配列は0x00A33211番地だ」というような仮定をすることができます。実行時には、このアドレスはMMUとOSによって実アドレス/ハードウェアアドレスに変換されます。
値が初期化されたスタティック・ストレージは、少し事情が異なります。例えば
int array[] = { 1 , 2 , 3 , 4 };
最初の例では、コンパイラは配列がどこに配置されるかを決定し、その情報を実行ファイルに保存するだけでした。
値が初期化されるものの場合、コンパイラは配列の初期値も実行ファイルに注入し、プログラム開始時の配列割り当て後に、配列にこれらの値を入れるようにプログラムローダに指示するコードも追加しています。
このコンパイラ(GCC4.8.1、x86ターゲット)が生成したアセンブリの例を2つ紹介します。
C++のコードです。
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
アセンブリを出力します。
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
見ての通り、値はアセンブリに直接注入されています。配列の中で
a
というのも、標準規格では、静的に保存されたものはデフォルトでゼロに初期化されるべきとされているからです。
8.5.9(イニシャライザ)【注】。
静的ストレージの持続時間のオブジェクトは、すべてゼロ初期化されます。 他の初期化が行われる前に、プログラムの起動が行われます。場合によっては 場合によっては、後で追加の初期化が行われます。
私はいつも、コンパイラがC++のコードに対して実際に何を行っているかを確認するために、コードを逆アセンブルするよう人々に勧めています。これは、(この質問のような)ストレージクラス/期間から高度なコンパイラ最適化まで適用されます。アセンブリを生成するようにコンパイラーに指示することもできますが、インターネット上にはこれを友好的に行う素晴らしいツールがあります。私のお気に入りは GCCエクスプローラ .
関連
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] Subversionリポジトリにおける「branch」、「tag」、「trunk」の意味とは?
-
[解決済み] C++11のT&&(ダブルアンパサンド)の意味とは?
-
[解決済み] ポインタの「デリファレンス」とはどういう意味ですか?
-
[解決済み] NSの接頭辞はどういう意味ですか?
-
[解決済み] ポーセリンとは、Gitではどのような意味ですか?
-
[解決済み] Pythonのオブジェクトが "subscriptable "であるかどうかは、どういう意味ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] なぜ.bssセグメントが必要なのですか?