ヒープにメモリを割り当てる場合、唯一の制限は空き RAM (または仮想メモリ) です。Gbのメモリになります。
では、なぜスタック サイズが非常に限られているのでしょうか (約 1 Mb) ? スタック上に非常に大きなオブジェクトを作成できない技術的な理由は何ですか?
更新:私の意図は明確ではないかもしれません。スタックに巨大なオブジェクトを割り当てたくないので、より大きなスタックは必要ありません。この質問は純粋な好奇心です。
ヒープにメモリを割り当てる場合、唯一の制限は空き RAM (または仮想メモリ) です。Gbのメモリになります。
では、なぜスタック サイズが非常に限られているのでしょうか (約 1 Mb) ? スタック上に非常に大きなオブジェクトを作成できない技術的な理由は何ですか?
更新:私の意図は明確ではないかもしれません。スタックに巨大なオブジェクトを割り当てたくないので、より大きなスタックは必要ありません。この質問は純粋な好奇心です。
あくまでもデフォルトサイズです。さらに必要な場合は、追加のスタック スペースを割り当てるようにリンカに指示することで、さらに取得できます。
大きなスタックを持つことの欠点は、多くのスレッドを作成すると、それぞれに 1 つのスタックが必要になることです。すべてのスタックがマルチ MB を割り当てているが、それを使用していない場合、スペースは無駄になります。
プログラムの適切なバランスを見つける必要があります。
@BJovke のような一部の人々は、仮想メモリは本質的に無料であると信じています。すべての仮想メモリをバックアップする物理メモリを用意する必要がないことは事実です。少なくとも仮想メモリにアドレスを割り当てることができる必要があります。
ただし、典型的な 32 ビット PC では、仮想メモリのサイズは物理メモリのサイズと同じです。これは、仮想かどうかに関係なく、どのアドレスにも 32 ビットしかないためです。
プロセス内のすべてのスレッドは同じアドレス空間を共有するため、それらの間でそれを分割する必要があります。そして、オペレーティング システムがその役割を果たすと、アプリケーション用に 2 ~ 3 GB しか残りません。アドレスがもうないため、そのサイズが物理メモリと仮想メモリの両方の制限になります。
近い方から遠い方の順番でスタックを考えてください。レジスタは CPU に近く (高速)、スタックは少し離れており (それでも比較的近い)、ヒープは遠くにあります (アクセスが遅い)。
もちろん、スタックはヒープ上に存在しますが、継続的に使用されるため、おそらく CPU キャッシュを離れることはなく、平均的なヒープ アクセスよりも高速になります。これは、スタックを適切なサイズに保つ理由です。可能な限りキャッシュされたままにします。大きなスタック オブジェクトの割り当て (オーバーフローが発生したときに自動的にスタックのサイズを変更する可能性があります) は、この原則に反します。
つまり、古い時代の名残りではなく、パフォーマンスの優れたパラダイムです。
大きなスタックが必要だと思うことの多くは、他の方法で行うことができます。
Sedgewick の「Algorithms」には、再帰を繰り返しに置き換えることによって、QuickSort などの再帰アルゴリズムから再帰を「削除」する良い例がいくつかあります。実際には、アルゴリズムは依然として再帰的であり、スタックも存在しますが、ランタイム スタックを使用するのではなく、ソート スタックをヒープに割り当てます。
(私は Pascal で与えられたアルゴリズムを備えた第 2 版を好みます。それは 8 ドルで使用できます。)
別の見方をすると、大きなスタックが必要だと思う場合、コードは非効率的です。より少ないスタックを使用するより良い方法があります。
技術的な理由はないと思いますが、スタック上にたった 1 つの巨大なスーパー オブジェクトを作成しただけの奇妙なアプリです。スタック オブジェクトには柔軟性がなく、サイズが大きくなると問題が大きくなります。スタック オブジェクトを破棄せずに戻ることはできず、他のスレッドにキューイングすることもできません。