スタックとスタックの違い--初心者に(積む)

8167 ワード

転自:http://bbs.chinaunix.net/thread-1973231-1-1.html
一、予備知識—プログラムのメモリ割り当てC/C++によってコンパイルされたプログラムが占有するメモリは以下のいくつかの部分1、スタック領域(stack):コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、局所変数の値などを格納する.その動作は、データ構造内のスタックに似ています.2、ヒープエリア(heap):一般的にプログラマーによってリリースが割り当てられ、プログラマーがリリースしない場合、プログラム終了時にOSによって回収される可能性がある.データ構造のスタックとは異なることに注意してください.割り当て方法はチェーンテーブルに似ています.3、グローバルゾーン(static):グローバル変数と静的変数の記憶はブロックに置かれ、初期化されたグローバル変数と静的変数はブロック領域にあり、初期化されていないグローバル変数と初期化されていない静的変数は隣接する別のブロック領域にあり、プログラム終了後にシステムが解放される.4、文字定数領域:定数文字列はここに置いてあり、プログラムが終わったらシステムから解放される.5、プログラムコード領域:関数体のバイナリコードを保存する.Example:
int a = 0; //        
char *p1; //         
main() 
{ 
int b; //   
char s[] = "abc"; //   
char *p2; //   
char *p3 = "123456"; // 123456\0    ,p3   。 
static int c =0//   (  )     
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); //      10 20         。 
strcpy(p1, "123456"); // 123456\0     ,         p3    "123456"       。 
}

 
 
二、スタックとスタックの理論知識2.1申請方式スタック:システムによって自動的に割り当てられる.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間のスタックを開きます:プログラマーが自分で申請する必要があって、そして大きさを指定して、cの中でmalloc関数:例えばp 1=(char*)malloc(10);C++では、p 2=(char*)malloc(10)などのnew演算子を使用します.ただし、p 1、p 2自体はスタック内にあることに注意してください.2.2申請後のシステムの応答スタック:スタックの残りの空間が申請した空間より大きい限り、システムはプログラムにメモリを提供する.そうしないと、異常提示スタックがオーバーフローする.≪ヒープ|Heap|emdw≫:まず、オペレーティング・システムに空きメモリ・アドレスを記録するチェーン・テーブルがあることを知っておく必要があります.システムがプログラムの申請を受信すると、チェーン・テーブルを巡り、申請した空間よりも大きな最初の空間のヒープ・ノードを探します.その後、そのノードを空きノード・チェーン・テーブルから削除し、そのノードの空間をプログラムに割り当てます.また、ほとんどのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てのサイズが記録され、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.2.3申請サイズの制限スタック:Windowsでは、スタックは低アドレスに拡張されたデータ構造であり、連続したメモリ領域である.スタックトップのアドレスとスタックの最大容量はシステムで予め定められており、WINDOWSではスタックの大きさは2 M(1 Mということもあり、つまり1つのコンパイル時に決定される定数)であり、申請された空間がスタックの残りの空間を超えるとoverflowが提示される.したがって、スタックから得られる空間は小さい.ヒープ:ヒープは高アドレスに拡張されたデータ構造で、不連続なメモリ領域です.これは,システムがチェーンテーブルで格納する空きメモリアドレスであるため,当然不連続であり,チェーンテーブルの遍歴方向は低アドレスから高アドレスである.スタックのサイズは、コンピュータシステムで有効な仮想メモリに制限されます.このことから,スタックが得られる空間は比較的柔軟であり,比較的大きいことが分かる.2.4申請効率の比較:スタック:システムによって自動的に割り当てられ、速度が速い.しかし、プログラマーはコントロールできません.スタック:newで割り当てられたメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.また、WINDOWSでは、VirtualAllocでメモリを割り当てるのが一番です.彼はスタックではなく、スタックではなく、プロセスのアドレス空間に直接高速メモリを残すのではなく、最も使いにくいです.しかし、スピードが速く、最も柔軟です.2.5スタックとスタック内のストレージコンテンツスタック:関数呼び出し時に、最初にスタックに入ったのは、メイン関数の次の命令(関数呼び出し文の次の実行可能文)のアドレスであり、次いで関数の各パラメータであり、ほとんどのCコンパイラでは、パラメータは右から左へスタックに入り、関数のローカル変数である.静的変数はスタックに入らないことに注意してください.今回の関数呼び出しが終了すると、ローカル変数は先にスタックを出て、それからパラメータで、最後にスタックトップポインタは最も最初に保存されたアドレス、つまりメイン関数の次の命令を指し、プログラムはこの点から実行を継続します.ヒープ:通常、ヒープのヘッダにヒープのサイズを1バイトで格納します.スタックの具体的な内容はプログラマーが手配します.2.6アクセス効率の比較
char s1[] = "aaaaaaaaaaaaaaa"; 
char *s2 = "bbbbbbbbbbbbbbbbb";

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbはコンパイル時に確定した.しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.例:
#include 
void main() 
{ 
char a = 1; 
char c[] = "1234567890"; 
char *p ="1234567890"; 
a = c[1]; 
a = p[1]; 
return; 
}

対応するアセンブリコード
10: a = c[1]; 
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 
0040106A 88 4D FC mov byte ptr [ebp-4],cl 
11: a = p[1]; 
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 
00401070 8A 42 01 mov al,byte ptr [edx+1] 
00401073 88 45 FC mov byte ptr [ebp-4],al

1つ目は、読み出し時に文字列の要素をレジスタclに直接読み出し、2つ目はポインタ値をedxに読み出し、edxに基づいて文字を読み出すのは明らかに遅い.2.7まとめ:スタックとスタックの違いは以下の比喩で見ることができる:スタックを使うのは私たちがレストランで食事をするのと同じで、注文(申請を出す)、お金を払う、食べる(使用する)だけで、満腹になったら行って、野菜を切る、野菜を洗うなどの準備と茶碗を洗う、鍋を洗うなどの掃除の仕事を気にする必要はありません.彼のメリットは速いですが、自由度は小さいです.山を使うのは自分で好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて、自由度が高いです.また、関数呼び出し時にスタックに一連のフィールドの保持とパラメータの伝達操作があります.スタックの空間サイズは限定され、VCのデフォルトは2 Mです.スタックが足りない場合は、プログラムに大量の配列と再帰関数階層が割り当てられているのが一般的です.関数呼び出しが終了して戻ると、関数内のすべてのスタック空間が解放されることを知っておく必要があります.スタックはコンパイラによって自動的に管理されているので、心配しないでください.スタックは動的にメモリを割り当て、大きなメモリを割り当てることができます.しかし、うまく使えないとメモリ漏れが発生します.また、頻繁にmallocとfreeは、Cがダイナミックメモリを割り当てるときに一致するメモリを探しているため、メモリフラグメント(ディスクフラグメントに似ている)を生成します.スタックでは破片は発生しません.スタックにデータをアクセスするのは、ポインタを介してスタックにデータをアクセスするよりも速い.一般的にスタックとスタックは同じで、スタック(stack)であり、スタックといえばスタックheapである.スタックは先入後出であり,一般に高アドレスから低アドレスに成長する.