c++コンパイラのメモリセグメント
5720 ワード
一、予備知識—プログラムのメモリ割り当て
c/C++でコンパイルされたプログラムによって消費されるメモリは、コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.データ構造のスタックに似ています.
2、ヒープエリア(heap)—一般的にプログラマーによって割り当てられて解放されるが、プログラマーが解放されない場合、プログラムの終了時にOSによって回収される可能性がある.データ構造中のヒープとは別物であることに注意し、割り当て方はチェーンテーブルに似ているが、ほほほ.
3、グローバル領域(静的領域)(static):グローバル変数と静的変数の記憶は一つのブロックに置かれている.初期化されたグローバル変数と静的変数は一つのブロックにあり、初期化されていないグローバル変数と初期化されていない静的変数は隣の別のブロックにある.プログラムがまとめられた後、システムによって解放される.
4、文字定数領域-定数文字列はここにあります.プログラムが終了するとシステムから解放されます.
5、プログラムコード領域
これは先輩が書いたもので、とても詳しいです.
二、スタックとスタックの理論知識申請方式 stack:システムによって自動的に割り当てられます.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間を開きます
Heap:プログラマーが自分で申請し、サイズを指定する必要があります.cではmalloc関数、例えばp 1=(char*)malloc(10)です.C++では、p 2=(char*)malloc(10)などのnew演算子を使用します.ただし、p 1、p 2自体はスタック内にあることに注意してください.申請後のシステムの応答 スタック:スタックの残りの領域が申請された領域より大きい場合、システムはプログラムにメモリを提供します.そうしないと、例外プロンプトスタックがオーバーフローします.
≪ヒープ|Heap|emdw≫:まず、オペレーティング・システムに空きメモリ・アドレスを記録するチェーン・テーブルがあることを知っておく必要があります.システムがプログラムの申請を受信すると、チェーン・テーブルを巡り、申請した空間よりも大きな最初の空間のヒープ・ノードを探します.その後、そのノードを空きノード・チェーン・テーブルから削除し、そのノードの空間をプログラムに割り当てます.また、ほとんどのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てのサイズが記録され、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.申請サイズの制限 スタック:Windowsの下で、スタックは低アドレスに拡張されたデータ構造で、連続したメモリの領域です.スタックトップのアドレスとスタックの最大容量はシステムで予め定められており、WINDOWSではスタックの大きさは2 M(つまり1 M、つまり1つのコンパイル時に決定される定数)であり、申請されたスペースがスタックの余剰スペースを超えるとoverflowが提示される.したがってスタックから得られるスペースは小さい.
ヒープ:ヒープは高アドレスに拡張されたデータ構造で、不連続なメモリ領域です.これは,システムがチェーンテーブルで格納する空きメモリアドレスであるため,当然不連続であり,チェーンテーブルの遍歴方向は低アドレスから高アドレスである.スタックのサイズは、コンピュータシステムで有効な仮想メモリに制限されます.このことから,スタックが得られる空間は比較的柔軟であり,比較的大きいことが分かる.出願効率の比較 スタック:システムによって自動的に割り当てられ、速度が速い.しかし、プログラマーはコントロールできません.
スタック:newで割り当てられたメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.また、WINDOWSでは、Virtual Allocでメモリを割り当てるのが一番です.彼はスタックではなく、スタックではなく、プロセスのアドレス空間に直接メモリを残しています.最も使いにくいですが.しかし、スピードが速く、最も柔軟です.スタックおよびスタック内の記憶内容 スタック:関数呼び出し時に、最初のスタックは、メイン関数の次のコマンドです.(関数呼び出し文の次の実行可能文)のアドレス、次に関数の各パラメータです.ほとんどのCコンパイラでは、パラメータは右から左へスタックに入り、次に関数のローカル変数になります.静的変数はスタックに入らないことに注意してください.今回の関数呼び出しが終了すると、ローカル変数は先にスタックを出て、パラメータになり、最後にスタックトップポインタは最初のメモリを指しますのアドレス、すなわち主関数の次の命令で、プログラムはその点で実行されます.
ヒープ:通常、ヒープのヘッダにヒープのサイズを1バイトで格納します.スタックの具体的な内容はプログラマーが手配します.アクセス効率の比較 char s1[]=”aaaaaaaaaaaaaaa”; char *s2=”bbbbbbbbbbbbbbbbb”; aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbはコンパイル時に確定した.
しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.例:
対応するアセンブリコード
1つ目は、読み出し時に文字列の要素をレジスタclに直接読み出し、2つ目はポインタ値をedxに読み出し、edxに基づいて文字を読み出すのは明らかに遅い.まとめ: スタックとスタックの違いは以下の比喩で見ることができる:スタックを使うのは私たちがレストランで食事をするのと同じで、料理を注文して(申請を出して)、お金を払って、食べて(使用して)、満腹になったら行って、野菜を切って、野菜を洗うなどの準備と茶碗を洗って、鍋を洗うなどの掃除の仕事を気にする必要はありません.彼のメリットは速いですが、自由度は小さいです.
山を使うのは自分で好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて、自由度が高いです.
自己総括:char*c 1=“abc”;実際にはまず文字定数領域に1つのブロック内に「abc」を格納し、スタックに1つのアドレスをc 1に割り当ててこのアドレスを指すと、定数「abc」を変更すると自然に崩壊するが、char c 2[]=「abc」であり、実際にはabcがメモリを格納する場所と上位者は異なり、4199056 2293624から完全に2つの場所であり、4199056が定数領域にあると推定される.一方、2293624がスタック領域2293628 2293624 2293620にある出力は、3つのポインタが割り当てられた領域がスタック領域であることを示し、高アドレスから低アドレス2293620 4199056 abcからコンパイラがc 3を定数領域に最適化した「abc」を示す
c/C++でコンパイルされたプログラムによって消費されるメモリは、コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.データ構造のスタックに似ています.
2、ヒープエリア(heap)—一般的にプログラマーによって割り当てられて解放されるが、プログラマーが解放されない場合、プログラムの終了時にOSによって回収される可能性がある.データ構造中のヒープとは別物であることに注意し、割り当て方はチェーンテーブルに似ているが、ほほほ.
3、グローバル領域(静的領域)(static):グローバル変数と静的変数の記憶は一つのブロックに置かれている.初期化されたグローバル変数と静的変数は一つのブロックにあり、初期化されていないグローバル変数と初期化されていない静的変数は隣の別のブロックにある.プログラムがまとめられた後、システムによって解放される.
4、文字定数領域-定数文字列はここにあります.プログラムが終了するとシステムから解放されます.
5、プログラムコード領域
これは先輩が書いたもので、とても詳しいです.
//main.cpp
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" 。
}
二、スタックとスタックの理論知識
Heap:プログラマーが自分で申請し、サイズを指定する必要があります.cではmalloc関数、例えばp 1=(char*)malloc(10)です.C++では、p 2=(char*)malloc(10)などのnew演算子を使用します.ただし、p 1、p 2自体はスタック内にあることに注意してください.
≪ヒープ|Heap|emdw≫:まず、オペレーティング・システムに空きメモリ・アドレスを記録するチェーン・テーブルがあることを知っておく必要があります.システムがプログラムの申請を受信すると、チェーン・テーブルを巡り、申請した空間よりも大きな最初の空間のヒープ・ノードを探します.その後、そのノードを空きノード・チェーン・テーブルから削除し、そのノードの空間をプログラムに割り当てます.また、ほとんどのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てのサイズが記録され、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.
ヒープ:ヒープは高アドレスに拡張されたデータ構造で、不連続なメモリ領域です.これは,システムがチェーンテーブルで格納する空きメモリアドレスであるため,当然不連続であり,チェーンテーブルの遍歴方向は低アドレスから高アドレスである.スタックのサイズは、コンピュータシステムで有効な仮想メモリに制限されます.このことから,スタックが得られる空間は比較的柔軟であり,比較的大きいことが分かる.
スタック:newで割り当てられたメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.また、WINDOWSでは、Virtual Allocでメモリを割り当てるのが一番です.彼はスタックではなく、スタックではなく、プロセスのアドレス空間に直接メモリを残しています.最も使いにくいですが.しかし、スピードが速く、最も柔軟です.
ヒープ:通常、ヒープのヘッダにヒープのサイズを1バイトで格納します.スタックの具体的な内容はプログラマーが手配します.
しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.例:
#include
voidmain()
{
char a=1;
char c[]="1234567890";
char *p="1234567890";
a = c[1];
a = p[1];
return;
}
対応するアセンブリコード
10:a=c[1];
004010678A4DF1 movcl,byteptr[ebp-0Fh]
0040106A884DF Cmovbyteptr[ebp-4],cl
11:a=p[1];
0040106D8B55EC movedx,dwordptr[ebp-14h]
004010708A4201 moval,byteptr[edx+1]
004010738845FC movbyteptr[ebp-4],al
1つ目は、読み出し時に文字列の要素をレジスタclに直接読み出し、2つ目はポインタ値をedxに読み出し、edxに基づいて文字を読み出すのは明らかに遅い.
山を使うのは自分で好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて、自由度が高いです.
自己総括:char*c 1=“abc”;実際にはまず文字定数領域に1つのブロック内に「abc」を格納し、スタックに1つのアドレスをc 1に割り当ててこのアドレスを指すと、定数「abc」を変更すると自然に崩壊するが、char c 2[]=「abc」であり、実際にはabcがメモリを格納する場所と上位者は異なり、4199056 2293624から完全に2つの場所であり、4199056が定数領域にあると推定される.一方、2293624がスタック領域2293628 2293624 2293620にある出力は、3つのポインタが割り当てられた領域がスタック領域であることを示し、高アドレスから低アドレス2293620 4199056 abcからコンパイラがc 3を定数領域に最適化した「abc」を示す