12

C/C++ では、変数、関数、メンバー関数、クラスのインスタンスをスタックまたはヒープに格納できます。

それぞれどのように実装されていますか?どのように管理されていますか (ハイレベル)? gcc は、スタックとヒープに使用するメモリのチャンクを事前に割り当ててから、要求に応じて解放しますか? 元のメモリはRAMから来ていますか?

スタックではなくヒープに関数を割り当てることはできますか?

明確化

ヒープメモリとスタックメモリの実装と管理について本当に質問しています。参照された質問を読んだ後、それに対処するものは何も見つかりませんでした...リンクをありがとう

4

2 に答える 2

6

最新のオペレーティング システムでは、ハードウェア RAM に直接アクセスすることはできず、代わりにいわゆる仮想メモリに抽象化され、オンデマンドで RAM にマップされます。通常、各プロセスには、完全なアドレス空間の独自のプライベート コピーが与えられます。これにより、OS は実行時にプロセスのメモリを RAM 内で移動したり、ディスクにスワップアウトしたりすることができます。これは透過的に行われます。つまり、プロセスはそのような再配置について通知されず、これを処理するためのコードは必要ありません。(一部のリアルタイム アプリケーションでは、メモリがスワップ アウトされるのを防ぐための手法が使用される場合があります)。

オブジェクト ファイルを実行可能ファイルまたは動的ライブラリにリンクする場合、リンカは関数/メソッドの cpu 命令とすべてのグローバル変数にメモリを静的に割り当てます。OS が実行可能ライブラリまたは動的ライブラリをロードすると、この事前に割り当てられたメモリが実際のメモリにマップされます。

起動時に、各スレッドはスタックと呼ばれるプライベート メモリ領域を受け取ります。関数/メソッドを呼び出すたびに、コンパイラは、関数/メソッドが使用するすべてのパラメーター、ローカル変数、および戻り値 (存在する場合) を保持するのに十分なメモリを (スタック ポインターをインクリメントすることによって) スタックから自動的に割り当てるコードを挿入します。コンパイラは、一部の変数をプロセッサ レジスタに残すだけで十分であると判断した場合、スタックにメモリを割り当てません。関数/メソッドが戻ると、コンパイラによって生成されたコードが実行され、(スタック ポインターをデクリメントすることによって) このメモリが解放されます。スタック上のオブジェクトのデストラクタは、それらが定義されているブロックが終了するときに呼び出されることに注意してください。これは、戻るまでに長い時間がかかる可能性があります。また、コンパイラは、割り当てられたメモリを自由に再利用できます。

例外がスローされると、コンパイラ コンパイラは、スタックのレイアウトを認識し、適切な例外ハンドラが見つかるまでそれをアンワインドできる特別なコードを挿入します。

これとは対照的に、ヒープ上のメモリはnew/を使用して割り当てられdelete、コンパイラはシステム ライブラリを使用してメモリを要求または解放するコードを挿入します。

これは、メモリ割り当てがどのように機能するかを理解するための簡単な説明であることに注意してください。

于 2009-08-03T10:50:59.413 に答える
5

基本的に、ヒープはコンパイラではなく、C ランタイム ライブラリによって実装されます。明らかに、このコードはプラットフォームに大きく依存しています。Unix または Unix ライクなシステムでは、実装は一般に sbrk/brk システム コールに基づいており、システム コールの数を減らすために大量のメモリが割り当てられます。このメモリは、ヒープ メモリ マネージャーによって管理されます。より多くのメモリが必要な場合は、sbrk への新しい呼び出しが発行されます。ヒープ管理ルーチンのデバッグに関心がある場合は、ヒープの現在の終了アドレスを sbrk(0) で取得できます。ほとんどのメモリ マネージャは、プロセスの存続期間中に OS にメモリを返さない (特定の制約が満たされている場合、gnu c ランタイム ライブラリは行います)。

より詳細な説明はhttp://gee.cs.oswego.edu/dl/html/malloc.htmlにあります。

于 2009-08-01T20:11:16.453 に答える