2

ヒープとスタックの違いがよくわからないことを指摘している可能性のあるコードを実行しています。以下にコード例をいくつか示します。ここでは、スタックまたは 1234567 要素のヒープで配列を宣言しています。どちらも機能します。

int main(int argc, char** argv){

  int N = 1234567;

  int A[N];

  //int* A = new int[N];

}

しかし、N を 12345678 とすると、int A[N] でセグ フォールトが発生しますが、ヒープ宣言は引き続き正常に機能します。(問題があれば g++ O3 -std=c++0x を使用しています)。これは何の狂気ですか?スタックには (かなり小さい) 配列サイズの制限がありますか?

4

2 に答える 2

6

これは、スタックのサイズがヒープよりもはるかに小さいためです。ヒープは、プログラムで使用可能なすべてのメモリを占有できます。デフォルトでは、VC++は1MBのサイズでスタックをコンパイルします。スタックはパフォーマンスが向上しますが、データ量が少なくなります。一般に、大規模なデータ構造には使用されません。これが、C++でlists/ arrays / dictionarys / ectを受け入れる関数が、通常、その構造体へのポインターまたは参照を受け取る理由です。値によって渡されたパラメーターはスタックにコピーされ、そのような構造体を渡すとプログラムがクラッシュすることがよくあります。

を使用している例ではN int、anintは4バイトです。これにより、サイズはA[N]約4.7 MBになり、スタックのサイズよりもはるかに大きくなります。

于 2012-11-29T23:30:58.950 に答える
2

ヒープは、malloc と co による割り当てで動的に拡大します。スタックは、プログラムの実行中に関数呼び出しが行われるたびに増加します。戻りアドレス、引数、ローカル変数は通常、スタックに格納されます (ただし、特定のプロセッサ アーキテクチャでは、これらの一部が代わりにレジスタに格納されます)。スタック領域を動的に割り当てることも可能です (ただし一般的ではありません)。

ヒープとスタックは、同じメモリの使用をめぐって競合します。一方が左から右に成長し、もう一方が右から左に成長すると考えることができます。放っておくと衝突する可能性があります。スタックは通常、特定の境界を超えて成長しないように制限されています。ほとんどの呼び出しで数バイトしか使用されず、使用されるスタック レベルも少ないと予想されるため、これは比較的小さいです。制限は小さいですが、ほとんどのタスクには十分です。ビルド設定を変更するか (Linux ELF バイナリの場合は除く)、setrlimit を呼び出すことで、この制限を拡張できます。OS によって制限が課される場合もありますが、これは変更できます。ソフト制限とハード制限がある場合があります (http://www.nics.tennessee.edu/node/327)。

制限についてさらに詳しく説明することは、質問の範囲外です。肝心なのは、スタックは制限されており、実際のメモリをめぐってヒープと競合するため非常に小さいということです。通常のアプリケーションでは、スタックを大きくする必要はありません。

http://en.wikipedia.org/wiki/Call_stack

于 2012-11-29T23:31:51.447 に答える