c++におけるメモリ割り当て方式


C/C++コンパイラによって使用されるメモリは、1、スタック領域(stack):コンパイラによって自動的に割り当てられて解放され、関数パラメータ値、ローカル変数値などが格納されます.その動作は、データ構造のスタックに似ています.2、ヒープエリア(heap):一般的にプログラマーによって割り当てられて解放され、プログラマーが解放されなければ、プログラムの終了時にOSによって回収される可能性があり、データ構造のヒープとは別で、割り当て方式はチェーンテーブルに似ている.3、グローバル領域(静的領域):グローバル変数と静的変数はブロックに格納され、初期化グローバル変数と静的変数はブロック領域にあり、非初期化グローバル変数と非初期化静的変数は隣接する別のブロック領域にある.プログラムが終了するとシステムから解放されます.4、文字定数領域-定数文字列はここにあります.プログラム終了後、システムから5、プログラムコード領域を解放する-関数体バイナリコードを格納する.二、例プログラム
//main.cpp
int a = 0;       
char *p1;        
main()
{
    int b; // 
    char s[] = "abc"; //s. 
    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申請方式stack:システムによって自動的に割り当てられる.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間heapを開きます:プログラマーが自分で申請する必要があって、そして大きさを指定して、cの中でmalloc関数はp 1=(char*)malloc(10)のようです;C++では、p 2=(char*)malloc(10)などのnew演算子を使用します.
ただし、p 1、p 2自体はスタック内にあることに注意してください.
2.2申請後のシステム応答スタック:スタックの残りの空間が申請した空間より大きい限り、システムはプログラムにメモリを提供する.そうしないと、異常提示スタックがオーバーフローする.
≪ヒープ|Heap|oem_src≫:オペレーティング・システムには空きメモリ・アドレスを記録するチェーン・テーブルがあり、システムがプログラムの申請を受信すると、チェーン・テーブルを巡回し、申請した空間よりも大きな最初の空間を探し、その後、そのノードを空きノード・チェーン・テーブルから削除し、プログラムに割り当てます.また、ほとんどのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てサイズが記録されます.これにより、コードのdelete文がこのメモリ領域を正しく解放できます.また、スタックポイントのサイズが申請サイズに等しいとは限らないため、余分な部分を空きチェーンテーブルに自動的に再配置します.
2.3申請サイズ制限
スタック:Windowsでは、スタックは低アドレスにデータ構造を拡張し、連続メモリ領域です.スタックトップアドレスとスタックの最大容量はシステムが予め規定しており、申請空間がスタックの残りの空間を超えると「stack overflow」と提示される.したがって、スタックからより小さなスペースを得ることができる.
ヒープ:ヒープは高アドレスにデータ構造を拡張し、不連続メモリ領域です.これは,システムが空きメモリアドレスをチェーンテーブルで格納しているため,当然不連続であり,チェーンテーブルの遍歴方向は低アドレスから高アドレスである.スタックサイズは、コンピュータシステム内の有効な仮想メモリに制限されます.このことから,スタック獲得空間は比較的柔軟であり,比較的大きいことが分かる.
2.4申請効率比較:スタックはシステムによって自動的に割り当てられ、速度が比較的速い.しかし、プログラマーはコントロールできません.スタックはnewで割り当てるメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.
また、WINDOWSでは、VirtualAllocでメモリを割り当てるのが最善です.彼はスタックではなく、スタックではなく、プロセスアドレス空間に直接高速メモリを残すのではなく、最も使いにくいです.しかし、スピードが速く、最も柔軟です.
2.5スタックとスタックにコンテンツスタックを格納する:関数呼び出し時、最初のスタックはメイン関数の次の命令(関数呼び出し文の次の実行可能文)アドレスであり、次いで関数の各パラメータであり、ほとんどのCコンパイラでは、パラメータは右から左へスタックに入り、関数のローカル変数である.静的変数はスタックに入らないことに注意してください.今回の関数呼び出しが終了すると、ローカル変数は先にスタックを出て、それからパラメータで、最後にスタックトップポインタは最初のメモリアドレス、つまりメイン関数の次の命令を指して、プログラムはこの点から実行を続けます.
≪ヒープ|Heap|emdw≫:一般的には、ヒープのサイズを1バイトで格納し、ヒープの具体的な内容はプログラマーが手配します.
2.6アクセス効率比較char s 1[]=「aaaaaaaaaaa」;char *s2 = "bbbbbbbbbbbbbbbbb"; aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbはコンパイル時に確定します.ただし、後でアクセスする場合、スタック上の配列はポインタが指す文字列(たとえばスタック)よりも速い.例:
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まとめ:スタックとスタックの違いは以下の比喩で見ることができる:スタックを使うのは私たちがレストランで食事をするように、注文(申請を出す)、お金を払う、食べる(使用する)だけで、満腹になったら行って、野菜を切る、野菜を洗うなどの準備と茶碗を洗う、鍋を洗うなどの掃除の仕事を気にする必要はありません.彼のメリットは速いですが、自由度は小さいです.山を使うのは自分で作って好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて自由度が高いです.
スタックにメモリを割り当てるのがスタックにメモリを割り当てるより遅いのはなぜですか?
スタック空間の開拓にはシステム関数が必要であり、スタック上でポインタを直接修正し、スタック空間管理にはシステム記帳が必要であり、スタック上の空間はコンパイラによって管理されたり、プロセッサレジスタに保存されたりすることができる.スタックスペースの解放にはシステム管理が必要であり、スタック上の解放は直接廃棄することができる.スタックスペースはスタックポインタで間接的に参照する必要があるため、アクセスが遅くなります.