2010-12-13 13 views
2

これは今長い間私を悩ませてきた。C++:関数の変数宣言は、内部的にどのように動作しますか?

void test(){ 
    int t1, t2, t3; 
    int t4 = 0; 
    int bigvar[10000]; 
    // do something 
} 

どのようにコンピュータが変数のためのメモリ割り当てを処理しない:私は機能を持っているとしましょうか?

私はいつも変数スペースがコンピュータが読み込む.exeに保存されていると考えてきましたが、これは正しいですか?しかし、私が知る限り、bigvar配列は、初期化されていないので、.exe内の要素スペースを10000 intとしていません。では、関数を呼び出すと、メモリ割り当てはどのように機能しますか?

+0

exeは_disk_に格納され、そこにコンパイルされたコードが格納されます。しかし、実行されると、_processor_ユニットからメモリが必要になります。ディスク内のバイトは、変数に必要なバイトに対応していません。 –

+0

http://stackoverflow.com/questions/556714/how-does-the-stack-work-in-assembly-language – karlphillip

答えて

9

これらのローカル変数は、通常、プロセッサのstackを使用して実装されます。つまり、コンパイラが行う必要があるのは、各変数のサイズを計算し、それらを加算することだけです。合計は、関数へのエントリでスタックポインタを変更し、終了時に変更するための量です。各変数は、スタック上のそのメモリブロックに相対オフセットでアクセスされます。

あなたのコードのLinuxでコンパイルする場合、x86のアセンブラでは、このように見える終わる、上記で

test: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $40016, %esp 
     movl $0, -4(%ebp) 
     leave 
     ret 

、定数$ 40016は、4つの32ビットint型t1, t2, t3t4に必要なスペースです残りの40000バイトは10000要素配列bigvarを占める。

+0

すてきな説明! – Nawaz

0

私はいくつかのノートを除いて、既に言われたことに多くを加えることができません。実際にローカル変数を実行可能ファイルに入れ、スタックセグメントの代わりにデータセグメントに割り当て(初期化)ます。これを行うには、staticと宣言します。しかし、関数のすべての呼び出しは同じ変数を共有しますが、スタックを呼び出すたびに新しい変数セットが作成されます。これは、関数が複数のスレッドによって同時に呼び出されたり、再帰があるとき(多くの場合、想像してみてください)に多くの問題を引き起こす可能性があります。だからこそ、ほとんどの言語はローカル変数にスタックを使用し、staticはめったに使用されません。

0

いくつかの古いコンパイラでは、配列が静的に割り当てられているという動作に遭遇しました。これは、プログラムをロードするときにメモリを確保し、その後にその領域を使用することを意味します。この動作は安全ではありません(Sergeyの回答を参照してください)。また、標準に従って許可されることも期待していませんが、私はそれを野生で遭遇しました。 (私はコンパイラが何であるかの記憶がありません)

ほとんどの場合、ローカル変数はリターンアドレスと他のすべてのものと共にスタックに保持されます。これは、初期化されていない値に機密情報が含まれている可能性があることを意味します。これには、アンワインドの回答ごとの配列も含まれます。

もう1つの有効な実装は、スタック上にある変数がポインタであり、コンパイラーが(おそらく例外セーフな方法で)割り当てと割り振りをフードの下で行うことです。これはスタック空間を節約し(プログラムの開始前に割り当てなければならず、x86アーキテクチャでは容易に拡張できない)、C標準VLA(可変長配列、別名:poor mans std :: vector)にも非常に有用です。

関連する問題