C++メモリアドレス割り当てとメモリ区分の概要


第一部C++メモリアドレス割り当ての概要
1メモリアドレスは、高アドレスから低アドレスに割り当てられます.
int i=1;
int j=1;
cout<<&i<<endl<<&j<<endl;   //  :0012FF60(    ) 0012FF54(    )

2関数パラメータリストの格納方式は,まず右端のパラメータに対してアドレスを割り当て,次に左端のパラメータに対してアドレスを割り当てる.
3 Little-endianモードのCPUによるオペランドの格納方式は低バイトから高バイトまで
0 x 1234の格納方法:
0X4000 0x34
0X4001 0x12
4 Big-endianモードのCPUによるオペランドの格納方式は、高バイトから低バイトまで
0 x 1234の格納方法:
0x4000 0x12
0x4001 0x34
5連合体unionの格納順序は,すべてのメンバが低アドレスから格納される.
6変数のアドレスは、メモリ領域の最下位アドレスによって表されます.
0X4000 0x34
0X4001 0x12
0 x 1234のアドレスビット0 x 4000
7スタックの割り当て方式は,高メモリアドレスから低メモリアドレスに割り当てられる.
int ivar=0;
int iarray[2]={11, 22};
注意iarray[2]は、値を割り当てるなど、境界を越えて使用されます.
iarray[2]=0;
では、同時にivarに0を付与すると、アドレスが同じであるため、すなわち&ivarは&iarray[2]に等しいため、デッドサイクルを生じる可能性がある.
 
第2部C/C++メモリ区分
一つはCにおいてこれらの記憶領域1に分ける.スタックはコンパイラによって自動的に割り当てられて解放されます.2.スタックは一般的にプログラマーによって割り当てられて解放され、プログラマーが解放されなければ、プログラムの終了時にOSによって回収される可能性がある.3.グローバルゾーン(静的領域)、グローバル変数と静的変数の記憶はブロックに置かれ、初期化されたグローバル変数と静的変数はブロック領域にあり、初期化されていないグローバル変数と初期化されていない静的変数は隣接する別のブロック領域にある.プログラムは解放を終了する.4.また、特別な定数を置く場所もある.プログラムは解放を終了する.関数体で定義される変数は通常スタック上でmalloc,calloc,reallocなどのメモリを割り当てる関数の割り当てはスタック上にある.すべての関数の体外で定義されるのはグローバル量です.static修飾子を付けると、どこにいてもグローバルゾーン(静的ゾーン)に格納され、すべての関数体外で定義されたstatic変数は、そのファイルに有効であることを示し、他のファイルにexternを使用することはできず、関数体内で定義されたstaticは、その関数体内でのみ有効であることを示す.また、関数中の「adgfdf」のような文字列は、定数ゾーンに格納される.例えば、
int  a = 0; //      
char *p1; //       
void main()
{     
int b;                   //      
char s[] = "abc"; //      
char *p2;         //      
char *p3 = "123456";       //123456{post.content}    ,p3        
static int c = 0;          //  (  )         
p1 = (char *)malloc(10);   //     10             
p2 = (char *)malloc(20);   //     20             
strcpy(p1, "123456");      //123456{post.content}     ,         p3    "123456"     
}

二.C++では、メモリは5つの領域に分けられ、それぞれスタック、スタック、自由記憶領域、グローバル/静的記憶領域、定数記憶領域1である.スタックは、コンパイラによって必要なときに割り当てられ、必要でないときに自動的に明らかになる変数の記憶領域です.中の変数は通常局所変数、関数パラメータなどです.2.スタックは、newによって割り当てられたメモリブロックであり、彼らの解放コンパイラは管理されず、私たちのアプリケーションによって制御され、一般的に1つのnewはdeleteに対応しなければならない.プログラマーが解放されていない場合は、プログラムが終了するとオペレーティングシステムが自動的に回収されます.3.フリーストレージエリアは、mallocなどによって割り当てられたメモリブロックで、スタックとよく似ていますが、freeで自分の命を終わらせています.4.グローバル/静的記憶領域、グローバル変数と静的変数は同じメモリに割り当てられ、以前のC言語では、グローバル変数は初期化されたものと初期化されていないものに分けられ、C++にはこの区別はなく、同じメモリ領域を共有していた.5.定数記憶領域、これは比較的特殊な記憶領域であり、彼らの中には定数が格納されており、修正は許されない(もちろん、不正な手段でも修正できる).bbsではスタックとスタックの区別問題は、永遠の話題のようだ.まず、void f(){int*p=new int[5];} 
この短い一言にはスタックとスタックが含まれています.newを見ると、まず、メモリのスタックを割り当てたと思います.ポインタpは?スタックメモリが割り当てられているので、スタックメモリにスタックメモリを指すポインタpが格納されていることを意味します.
プログラムはまずスタックに割り当てられたメモリのサイズを決定し、operator newを呼び出してメモリを割り当て、その後、このメモリのヘッダアドレスを返してスタックに入れ、VC 6の下のアセンブリコードは以下の通りである:00401028 push 14 h 0040102 A call operator new(00401060)0040102 F add esp、4 00401032 mov dword ptr[ebp-8],eax 00401035 mov eax,dword ptr[ebp-8]00401038 mov dword ptr[ebp-4]、eaxここでは、簡単にメモリを解放していないので、どうやって解放すればいいのでしょうか.delete pですか?間違っています.delete[]pのはずです.これはコンパイラに伝えます.私が削除したのは配列です.VC 6は対応するCookie情報に基づいてメモリを解放する仕事をします.では、私たちは私たちのテーマに戻ります.スタックとスタックにはいったいどんな違いがありますか.主な違いは以下の点である:1、管理方式が異なる;2、空間の大きさが違う.3、破片ができるかどうか.4、成長方向が違う.5、分配方式が違う;6、分配効率が違う;管理方式:スタックにとって、コンパイラによって自動的に管理され、手動で制御する必要はありません.スタックにとって、解放作業はプログラマーによって制御され、memory leakが発生しやすい.空間サイズ:一般的に32ビットシステムでは、スタックメモリは4 Gの空間に達することができ、この観点からスタックメモリはほとんど制限されていない.しかしスタックの場合、一般的には一定の空間サイズがあり、例えば、VC 6の下には、デフォルトのスタックスペースサイズは1 Mです(はっきり覚えていないようです).もちろん、プロジェクトを開き、メニューを順に操作します.Project->Settings->Link、CategoryでOutputを選択し、Reserveでスタックの最大値とcommitを設定します.注意:Reserveの最小値は4 Byte、commitは仮想メモリのページファイルに保存されており、設定が大きくなりますスタックは大きな値を開き、メモリのオーバーヘッドと起動時間を増加させる可能性があります.フラグメントの問題:スタックにとって、頻繁なnew/deleteはメモリ空間の不連続をもたらし、大量のフラグメントをもたらし、プログラムの効率を低下させるに違いない.スタックにとって、この問題は存在しません.スタックは先進的な後出キューであるため、彼らはこのように対応しており、スタックの間からメモリブロックがポップアップされることは永遠に不可能です.ポップアップする前に、その上の後進的なスタックの内容がポップアップされ、詳細はデータ構造を参照することができます.ここでは、一つ一つ議論しません.成長方向:スタックにとって、成長方向は上向き、すなわちメモリアドレスが増加する方向である.スタックの場合、その成長方向は下向きであり、メモリアドレスが減少する方向に成長します.割り当て方法:スタックはすべて動的に割り当てられ、静的に割り当てられていないスタックです.スタックには、静的割当てと動的割当ての2つの割当て方式があります.静的割当ては、ローカル変数の割当てなど、コンパイラによって完了します.動的割り当てはalloca関数によって割り当てられますが、スタックの動的割り当てとスタックは異なり、その動的割り当てはコンパイラによって解放され、手動で実現する必要はありません.分配効率:スタックは機械システムが提供するデータ構造であり、コンピュータは底層でスタックにサポートを提供する:専門のレジスタ格納スタックのアドレスを分配し、スタックを押し出すには専門的な命令が実行され、これはスタックの効率が比較的高いことを決定した(私の注釈:EBPレジスタについては別の文章を参照してください).
スタックはC/C++関数ライブラリで提供され、そのメカニズムは複雑です.例えば、メモリを割り当てるために、ライブラリ関数は、データ構造/オペレーティングシステムを参照できる特定のアルゴリズムに従って、十分なサイズのスペースがない場合、スタックメモリで使用可能な十分なサイズのスペースを検索します.(メモリフラグメントが多すぎるためかもしれませんが)、システム機能を呼び出してプログラムデータセグメントのメモリ領域を増やすことができ、十分なサイズのメモリに分けて返す機会があります.スタックの効率はスタックよりずっと低いことは明らかです.ここから、スタックはスタックに比べてnew/deleteの使用が多く、メモリフラグメントが大量に発生しやすいことがわかります.;専門的なシステムサポートがないため、効率が低い.ユーザ状態とコア状態の切り替えを引き起こす可能性があるため、メモリの申請は、より高価になります.したがって、スタックはプログラムの中で最も広く応用されており、関数の呼び出しでもスタックを利用して完了し、関数呼び出し中のパラメータ、戻りアドレス、EBP、ローカル変数はスタック方式で保存されている.だから、スタックではなくスタックを使うことをお勧めします.スタックには多くのメリットがありますが、スタックに比べてそれほど柔軟ではないため、大量のメモリスペースを割り当てる場合があります.スタックを使うほうがいいです. 
スタックでもスタックでも、国境を越えた現象の発生を防止しなければならない.(わざと境界を越えない限り)、境界を越えた結果はプログラムが崩壊するか、プログラムのスタック、スタック構造を破壊し、予想外の結果を生むかのどちらかだから、プログラムの実行中でも、上記の問題が発生していない場合でも、いつ崩壊するか分からないので、debugはかなり難しいです.)