何が起きているのかをよりよく理解するために、一度に1つのプロセスしか実行できない16ビットプロセッサで動作する非常に基本的なオペレーティングシステムしかないとしましょう。つまり、一度に実行できるプログラムは1つだけです。さらに、すべての割り込みが無効になっているようなふりをしましょう。
私たちのプロセッサには、スタックと呼ばれる構造があります。スタックは、物理メモリに課せられた論理構造です。私たちのRAMがアドレスE000〜FFFFに存在するとしましょう。これは実行中のプログラムがこのメモリをどんな方法でも使用できることを意味します。私たちのオペレーティングシステムが、E000〜EFFFがスタックであり、F000〜FFFFがヒープであると言っているとしましょう。
スタックは、ハードウェアと機械の指示によって維持されます。それを維持するために必要なことはあまりありません。私たち(または私たちのOS)が行う必要があるのは、スタックの開始アドレスを適切に設定することです。スタックポインタは、ハードウェア(プロセッサ)内に存在する物理エンティティであり、プロセッサ命令によって管理される。この場合、スタックポインタはEFFFに設定されます(スタックがBACKWARDSを成長すると仮定しますが、これはかなり一般的です)。 Cのようなコンパイル言語では、関数を呼び出すと、渡された引数をスタックの関数にプッシュします。各引数には一定のサイズがあります。 intは通常16または32ビット、charは通常8ビットなどです。私たちのシステムでは、intとint *が16ビットのふりをしましょう。各引数について、スタックポインタはsizeof(引数)によってDECREMENTED( - )され、引数はスタックにコピーされます。スコープ内で宣言した変数は、同じ方法でスタックにプッシュされますが、その値は初期化されません。
2つの例に似た2つの例を考えてみましょう。スタックに 1)プッシュeeep:当社の16ビットシステム上で、ここで何が起こる
int hello(int eeep)
{
int i;
int *p;
}
は次のとおりです。つまり、sizeof(int)が2であるため、スタックポインタをEFFDにデクリメントしてから実際にeeepをEFFEにコピーします(スタックポインタの現在の値から1を引いたものです。割り当て後)。時には、両方で実行できる命令があります(レジスタに収まるデータをコピーしていると仮定します。そうでなければ、データ型の各要素をスタック上の適切な場所に手動でコピーする必要があります)。 )。
2)iのスペースを作成します。これはおそらく、スタックポインタをEFFBにデクリメントすることを意味します。
3)pのスペースを作成します。これは、おそらくスタックポインタをEFF9にデクリメントすることを意味します。
私たちのプログラムは、変数がどこにあるのかを記憶しています(eeepはEFFE、iはEFFC、pはEFFA)。覚えておくべき重要なことは、スタックがBACKWARDSをカウントしても変数がFORWARDSで動作していることです(これは実際にエンディアンに依存しますが、その点は& eeep == EFFE、EFFFではありません)。
機能が閉じたとき、我々は単に6で(++)、スタックポインタをインクリメントは、(C++の種類、大きさ2のがスタックにプッシュされていない、3「オブジェクト」からです。今
、それは、インターネット上で説明するのはほぼ不可能だと、それを達成するための非常に多くの方法があるので、あなたの2番目のシナリオは、はるかに困難を説明することです。
int hello(int eeep)
{
int *p = malloc(sizeof(int));//C's pseudo-equivalent of new
free(p);//C's pseudo-equivalent of delete
}
eeepおよびpはまだ前にとしてスタックにプッシュし、割り当てられていますしかし、この場合は、pを関数呼び出しの結果に初期化します。malloc(またはnew、newはC++で多くのことを行います。必要に応じて、必要に応じて、必要に応じて、必要に応じて、作成者など)は、HEAPと呼ばれるこのブラックボックスに行き、空きメモリのアドレスを取得します。私たちのオペレーティングシステムは、私たちのためにヒープを管理しますが、いつ私たちがメモリを必要としているのか、それが終わった時を知らせる必要があります。
例では、malloc()を呼び出すと、OSはこれらのバイトの開始アドレスを与えることで2バイトのブロック(システム上のsizeof(int)は2)を返します。最初の呼び出しでF000のアドレスが指定されたとしましょう。 OSは、アドレスのF000とF001が現在使用中であることを追跡します。 free(p)を呼び出すと、OSはpが指し示すメモリブロックを見つけ、sizeof(star p)が2であるため2バイトを未使用としてマークします。代わりに、より多くのメモリを割り当てると、アドレスF002が新しいメモリの開始ブロックとして返される可能性があります。 malloc()自体は関数であることに注意してください。 pがmalloc()の呼び出しのためにスタックにプッシュされると、pはpのサイズに合わせてスタック上に十分な空き領域を持つ最初の開かれたアドレスでスタックに再度コピーされます(おそらくEFFB、 sizeof(p)は2です)、スタックポインタは再びEFF9にデクリメントされ、malloc()はそのローカル変数をこの位置からスタックに配置します。 mallocが終了すると、スタックからすべての項目がポップされ、スタックポインタが呼び出される前の状態にスタックポインタが設定されます。空の星であるmalloc()の戻り値は、私たちの使用のためにいくつかのレジスタ(通常は多くのシステムのアキュムレータ)に配置される可能性があります。
実装では、両方の例が本当に簡単ではありません。新しい関数呼び出しのためにスタックメモリを割り当てるときは、新しい関数が値を永久に消去しないように状態を保存する(すべてのレジスタを保存する)ことを確認する必要があります。これは通常、スタック上にプッシュすることも含みます。同じように、通常はプログラムカウンタレジスタを保存して、サブルーチンが復帰した後に正しい場所に戻ることができます。メモリマネージャは、どのメモリが割り当てられているか、割り当てられていないかを「記憶」するために、自分のメモリを使い切ります。仮想メモリとメモリのセグメンテーションはこのプロセスをさらに複雑にし、メモリ管理アルゴリズムはメモリの断片化(それ自体の話題全体)を防ぐために、ブロックを周りに移動して保護しなければならず、これが仮想メモリにつながります同じように。 2番目の例は、実際には最初の例と比較して、ワームの大きな缶です。さらに、複数のプロセスを実行すると、各プロセスが独自のスタックを持ち、複数のプロセス(つまり、自身を保護する必要があります)によってヒープにアクセスすることができるため、この作業は非常に複雑になります。さらに、各プロセッサのアーキテクチャは異なります。いくつかのアーキテクチャでは、スタックポインタをスタック上の最初の空きアドレスに設定することを期待していますが、他のアーキテクチャでは、それを最初のフリーでない場所に向けることを期待しています。
私はこれが助けてくれることを望みます。私にお知らせください。
注意すべての上記の例は、過度に簡略化された架空のマシン用です。実際のハードウェア上では、これは少し毛深くなります。
編集:アスタリスクが表示されません。我々は例に(ほとんど)同じコードを使用する場合、私たちは、それぞれ「例1」と「例2」と「こんにちは」置き換えて、それは価値がある何のための単語「スター」
でそれらを置き換えますwndows上でintelの次のアセンブラ出力を取得します。
.file "test1.c"
.text
.globl _example1
.def _example1; .scl 2; .type 32; .endef
_example1:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
leave
ret
.globl _example2
.def _example2; .scl 2; .type 32; .endef
_example2:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $4, (%esp)
call _malloc
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, (%esp)
call _free
leave
ret
.def _free; .scl 3; .type 32; .endef
.def _malloc; .scl 3; .type 32; .endef
どのように同じメモリ割り当てを使用できますか?最初のものはint(スタック上)とポインタ(スタック上)のサイズを割り当てます。 2番目の関数は、スタック上のポインタとヒープ上のintのためのスペースを割り当てます。 – bobbyalex
基本的に私の質問は「実行時に、スタックとヒープの違いは何ですか? – Tarquila
ここをクリックしてください:http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap – Alex