7

C ++(およびC)を研究しているときに、スタック割り当ての動作に関していくつかの特定の疑問がありました。それは、次の解決策を見つけることができないということです。

  1. スタック割り当てはmalloc/free関数を暗黙的に呼び出しますか?そうでない場合; スタック割り当てとヒープ割り当ての間に競合がないことをどのように保証しますか?

  2. そうであれば; C++のスタック割り当ては暗黙的にnew/ deleteも呼び出しますか?そうであれば; クラスの新しい演算子をオーバーロードすると、そのスタック割り当てに影響しますか?

それはVC++で紛らわしい結果をもたらしました。しかし、VC ++は完全に標準に準拠しているわけではないので(またはそう聞いたので)、ここで質問したほうがいいと思いました...

4

7 に答える 7

26

スタック割り当ては、malloc/freeのようなものを使用しません。これは、プログラムスタックと呼ばれるメモリの一部を使用します。これは、メモリの連続したセグメントにすぎません。

スタックの最上位を格納する特殊レジスターがあります。スタック上に新しいオブジェクトが作成されると、トップが上がり、スタックが増加します。オブジェクトの割り当てが解除される(スコープ外になる)と、トップが下がり、スタックが減少します。

スタックに大きすぎるオブジェクトを割り当てようとしたり、再帰に深く入りすぎたりすると、トップはスタックの最大許容サイズを超えてしまい、これはスタックオーバーフローと呼ばれます。

注:スタックの実際の増加方向(アドレスの増加または減少)はシステムによって異なりますが、一般的な考え方は実際の方向に関係なく同じです。

于 2009-03-26T12:44:37.687 に答える
17

最初の質問に対する答えは「いいえ」です。スタックはヒープからまったく割り当てられません。

基本的な概念を理解するには、最初にスタックとヒープが何でどこにあるかを読む必要があります。

于 2009-03-26T12:42:25.400 に答える
6

ここに良い質問があります:

「スタック割り当てとヒープ割り当ての間に競合がないことをどのように保証しますか?」

ほとんどすべてのC/C ++実装には、単一の連続したアドレススペースがあるため、スタックとヒープに割り当てられたメモリは、そのスペースに共存する必要があります。

スタックが拡大および縮小するたびに、これは個々のヒープ割り当てでは実行されませんが、スタックは、ヒープから割り当てられた単一の大きなメモリブロックと考えることができます。スタックがそのブロックの境界を超えて大きくなると、スタックオーバーフローが発生します(キャッチーな名前...誰かがそれにちなんでWebサイトに名前を付ける必要があります)。

マルチスレッドプログラムでは、スレッドが開始するたびに新しいスタックを割り当てる必要があり、スレッドが終了するとスタックの割り当てを解除できます。mallocそして、これらのスタック全体のブロックが、 /を介して公開されるのと同じヒープ管理を使用して割り当てられることは理にかなっていますfree

つまり、大まかに言えば、スタックはヒープ内に共存する一種のオブジェクトであると考えることができます。スレッドが起動すると、スタック全体mallocが一度に-edされ、次にそこからサブ割り当てされ、次にfree-dが一度に取得されます。

Windowsでは、(危険な状態で生活したい場合は)同じ仮想メモリAPIを自分で呼び出して、スタックについて調べ、スタック内の仮想ページを強制的に解放することができます。

于 2009-03-26T13:31:49.897 に答える
6

スタック割り当ては通常、 alloca() によって、またはコンパイラによって暗黙的に行われます。よくできた alloca() は、ごくわずかな命令しか必要とせず、完了時にそれを解放するためのコスト (またはその必要さえありません) はありません。

alloca() によって割り当てられたメモリへのポインターを、ポインターを必要とする他の関数/メソッドに渡すことができます。alloca() によって割り当てられたポインタを返してはなりません。

スタック割り当てを使用する利点欠点を次に示します。

于 2009-03-26T12:47:09.647 に答える
5

C および C++ では、関数呼び出しの有効期間にわたってオブジェクトが作成される「自動」と、ランタイムによって提供される関数によって一部のメモリが割り当てられる「動的」の 2 種類のメモリ割り当てがあります。

ランタイム実装の大部分では、自動オブジェクトは、スレッドの作成時にオペレーティング システムによって提供される連続したスタックを使用して割り当てられます。スタックは通常、高い値のアドレスから始まり、オブジェクトのサイズだけ減分されます。動的割り当て (C の malloc、C++ の新機能) は、オペレーティング システムから要求された他のメモリを使用します。OS はスタックが使用しているアドレスを認識しているため、動的要求に同じアドレスを割り当てません。動的領域は順序付けられていないため、ヒープと呼ばれることがよくあります。

したがって、「スタック」割り当ては malloc/free しません。C++ の自動オブジェクトは、コンストラクターとデストラクタを呼び出しますが、new と delete は呼び出しません。これは、new と delete にも動的メモリを管理するコードがあるためです。

于 2009-03-26T12:55:28.580 に答える
1

いいえ、スタック割り当てはmalloc/freeを呼び出しません。スタックスペース全体は、プログラムの開始時に割り当てられます。各関数に入ると、スタックポインターは十分に進められ、スタックに割り当てられた変数が存在する「スタックフレーム」用のスタック上のスペースを確保します。

于 2009-03-26T12:44:21.527 に答える
1

Kepp は、「スタック割り当て」が実装の詳細であることを念頭に置いています。スタックが自動ストレージに使用されるという保証はありません。たとえば、伝承の IBM メインフレームはそうではありませんでした (ただし、最新のマシンではそうだと言われています)。

于 2009-03-26T14:09:49.637 に答える