4

スタックは貴重なリソースであるため、スタック割り当て配列を使用しないように言われました。実際、配列が比較的小さい限り、スタックに割り当てられた配列を使用してもまったく問題ないと他の人が私に提案しました。

一般的な経験則を持ちたいと思います: スタックに割り当てられた配列をいつ使用する必要がありますか? また、いつヒープ割り当て配列を使用する必要がありますか?

4

5 に答える 5

3

すべてのメモリには限りがありますが、膨大な量の RAM と仮想メモリを使用している今日でも、まだ限界があります。ただし、特に、小規模な組み込みシステムで数キロバイトから PC で数メガバイトになる可能性があるスタックと比較すると、かなり大きくなります。

それ以外に、それをどのように、何のために使用しているかという質問もあります。たとえば、関数から「配列」を返したい場合、それはスタック上にあってはなりません。

一般的に、可能であれば、スタック上の配列を小さく保つようにしてください。スタック上に何千ものエントリを持つ配列を作成している場合は、立ち止まって、それが何のために必要かを考えるべきです。

于 2012-08-17T11:07:01.307 に答える
2

プラットフォームによって異なります。

現在、人気のある x64 プラットフォームで作業している場合は、特に心配する必要はありません。

使用しているオペレーティング システムに応じて、ユーザーランド プロセスが使用できるスタック領域とヒープ領域を確認できます。

たとえば、UNIX ライクなシステムにはソフト制限とハード制限があります。クランクアップできるものもあれば、できないものもあります。

要するに、通常はそのようなことを心配する必要はありません。そして、知る必要があるときは、通常、開発しようとしているプラ​​ットフォームと密接に結びついているため、これらすべての詳細を知っています。

あなたの質問に答えていただければ幸いです。特定の値が必要な場合は、正確なハードウェア、オペレーティング システム、およびユーザー権限を指定してください。

于 2012-08-17T11:10:27.477 に答える
1

この質問に対する答えは、文脈によって異なります。たとえば、オペレーティング システム カーネル用に記述する場合、スタックはかなり制限されている可能性があり、スタック フレームに 1,000 バイトを超える割り当てを行うと問題が発生する可能性があります。

最新のコンシューマ システムでは、スタックに使用できるスペースは通常非常に大きいです。システムがかつて抱えていた問題の 1 つは、アドレス空間が限られており、スタックにアドレスが割り当てられると、物理メモリの可用性に関係なく、スタックの成長方向にアドレス空間内の次のオブジェクトよりも大きくならないことでした。またはアドレス空間の他の場所にある仮想メモリの。これは、今日のアドレス空間ではあまり問題になりません。

一般に、メガバイト単位のスペースをスタック フレームに割り当てることができ、それを行うのは安価で簡単です。ただし、大量のスペースを割り当てる多くのルーチンが呼び出された場合、または大量のスペースを割り当てた 1 つまたはいくつかのルーチンが再帰的に呼び出された場合、使用されるスペースが多すぎて何らかの制限 (アドレス空間など) に達するため、問題が発生する可能性があります。または物理メモリ)。

もちろん、ヒープからスペースを割り当てても、物理メモリの制限に達することは緩和されません。したがって、スタックに使用できるアドレス空間を消費するという問題だけが、スタックとヒープのどちらを使用するかという問題に関連しています。

これが問題であるかどうかの簡単なテストは、大量のスタック スペースの使用をmainルーチンに挿入することです。追加のスタック スペースを使用し、通常は大量のスタック スペースを使用する負荷の下でアプリケーションが引き続き機能する場合、 でこの人為的な予約を削除するmainと、十分なマージンが得られます。

より良い方法は、プログラムが使用できる最大値を計算し、それをシステムから利用可能なスタック領域と比較することです。しかし、今日のソフトウェアでは、それが容易なことはめったにありません。

スタック スペースの制限に達している場合は、リンカーまたはオペレーティング システムに、より多くのスペースを利用できるようにするオプションがある場合があります。

于 2012-08-17T11:14:38.820 に答える
1

グローバル変数と静的変数のスコープは、プロセスの存続期間全体になります。これらの変数のメモリは、プロセスの開始時に割り当てられ、プロセスの終了時にのみ解放されます。

ただし、ローカル変数(スタック変数)は、それが定義されている関数にのみスコープを持ちます。関数が呼び出されるとメモリが割り当てられ、制御が関数から終了すると解放されます。

動的メモリの主な目的は、ユーザー定義のスコープの変数を作成することです。変数手段のスコープを制御したい場合は、x1 つの関数で変数にメモリを割り当ててから、必要な数の関数に参照 (アドレス) を渡し、最後にそれを解放することができます。

したがって、動的に割り当てられたメモリの助けを借りて、ローカル変数よりもスコープが大きく、グローバルまたは静的変数よりもスコープが小さい変数を作成できます。

これとは別に、アーキテクチャにメモリの制約がある場合は、サイズが非常に大きい場合は動的メモリを使用することをお勧めします。

于 2012-08-17T12:30:30.817 に答える
0

ヒープ割り当てメモリを使用する正当な理由は、その所有権を他の関数/構造体に渡すことです。一方、スタックは無料でメモリ管理を提供し、スタックからメモリを解放することを忘れることはできませんが、ヒープを使用するとリークのリスクがあります。

ローカルで使用するためだけに配列を作成する場合、使用するサイズの基準ですが、正確なサイズを指定するのは難しく、それを超えるとメモリをヒープに割り当てる必要があります。ヒープに移動するには数百バイトで十分であると言えますが、それよりも少ないか多い場合もあります。

于 2012-08-17T11:06:14.303 に答える