8

たとえば、私はできる

int *arr;
arr = (int *)malloc(sizeof(int) * 1048575);

しかし、プログラムがクラッシュせずにこれを行うことはできません:

int arr[1048575];

これはなぜですか?

4

3 に答える 3

11

arrがローカル変数であると仮定すると、それを配列として宣言すると、(比較的制限された) スタックからのメモリが使用され、(比較的制限のないmalloc()) ヒープからのメモリが使用されます。

于 2011-06-29T03:05:40.710 に答える
2

これらを関数内のローカル変数として割り当てている場合 (ポインター宣言の直後にmalloc呼び出しを行うことができる唯一の場所です)、違いはmalloc、ヒープからメモリのチャンクを割り当て、そのアドレスを提供することです。直接実行int arr[1048575];すると、スタックにメモリを割り当てようとします。スタックに使用できるスペースがはるかに少なくなります。

スタックのサイズは、私が認識している 2 つの主な理由で制限されています。

  1. 従来の命令型プログラミングは再帰をほとんど使用しないため、深い再帰 (および大量のスタックの成長) は「おそらく」無限再帰の兆候であり、したがってプロセスを強制終了するバグです。したがって、プロセスがアドレス空間を使い果たす原因となるギガバイトの仮想メモリ (32 ビット アーキテクチャ上) をプロセスが消費するにキャッチされるのが最善です (その時点で、マシンは実際よりもはるかに多くの仮想メモリを使用している可能性があります)。 RAM、したがって、動作が非常に遅くなります)。
  2. マルチスレッド プログラムには、複数のスタックが必要です。したがって、ランタイム システムは、スタックが特定の境界を超えて成長しないことを認識する必要があるため、新しいスレッドが作成された場合に、その境界の後に別のスタックを配置できます。
于 2011-06-29T03:08:09.977 に答える
1

配列を宣言すると、スタックに配置されます。

malloc() を呼び出すと、メモリがヒープから取得されます。

通常、スタックはヒープに比べてより制限されており、通常は一時的です (ただし、この配列が宣言されている関数に出入りする頻度によって異なります。

このような大規模な (おそらく今日の標準ではありませんか?) メモリの場合は、配列をしばらく存続させたいと仮定して、メモリを malloc することをお勧めします。

于 2011-06-29T03:10:42.587 に答える