C++におけるスタック変数の簡単な解析

9802 ワード

C++では、メモリはスタック、スタック、フリーストレージ、グローバル/静的ストレージ、定数ストレージの5つの領域に分かれています.スタックとは、コンパイラによって必要なときに割り当てられ、必要でないときに自動的に消去される変数の記憶領域です.中の変数は通常局所変数、関数パラメータなどです.スタックは、newによって割り当てられたメモリブロックであり、彼らの解放コンパイラは管理されず、私たちのアプリケーションによって制御され、一般的に1つのnewはdeleteに対応しなければならない.プログラマーが解放されていない場合は、プログラムが終了するとオペレーティングシステムが自動的に回収されます.フリーストレージエリアは、mallocなどで割り当てられたメモリブロックで、スタックとよく似ていますが、freeで自分の命を終わらせています.グローバル/静的記憶領域では、グローバル変数と静的変数が同じメモリに割り当てられ、以前のC言語では、グローバル変数は初期化されたものと初期化されていないものに分けられ、C++にはこの区別はなく、同じメモリ領域を共有していました.定量記憶領域、これは比較的特殊な記憶領域で、彼らの中には定量が保存されており、修正は許されない(もちろん、不正な手段でも修正することができ、方法が多い.
int  a;  
  void  func(int arg)  
  {
       
        static int b;  
        int  c;  
        void  *p;  
        p   =   (void *)malloc(100);  
  }  

aファイル中でグローバル変数bと宣言する関数内で宣言するが静的であるため、グローバルデータ領域c,pは関数内で宣言し、スタック変数argはパラメータであり、スタック変数pが指す空間はmallocで割り当てられ、スタック空間である
一、予備知識—プログラムのメモリ割り当て
C/C++でコンパイルされたプログラムによって使用されるメモリは、コンパイラによって自動的に割り当てられ、関数のパラメータ値、ローカル変数の値などが格納されます.その動作は、データ構造内のスタックに似ています.2、ヒープエリア(heap)—一般的にプログラマーによってリリースが割り当てられ、プログラマーがリリースしない場合、プログラム終了時にOSによって回収される可能性がある.データ構造のスタックとは異なることに注意してください.割り当て方法はチェーンテーブルに似ています.3、グローバル領域(静的領域)-、グローバル変数と静的変数の記憶はブロックにあり、初期化されたグローバル変数と静的変数はブロック領域にあり、初期化されていないグローバル変数と初期化されていない静的変数は隣接する別のブロック領域にある.-プログラム終了後にシステムリリース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 20strcpy(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|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はコンパイル時に確定した.しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.例えば、#i nclude 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]; 0040106 D 8 B 55 EC mov edx,dword ptr[ebp-14 h]00401070 8 A 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まとめ:スタックとスタックの違いは以下の比喩で見ることができる:スタックを使うのは私たちがレストランで食事をするのと同じで、注文(申請を出す)、お金を払う、食べる(使用する)だけで、満腹になったら行って、野菜を切る、野菜を洗うなどの準備と茶碗を洗う、鍋を洗うなどの掃除の仕事を気にする必要はありません.彼のメリットは速いですが、自由度は小さいです.山を使うのは自分で好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて、自由度が高いです.
後記
スタックとスタックの違いは主にオペレーティングシステムのスタックとスタックに分けられ、上記のように、多くは言いません.また、データ構造のスタックとスタックもあり、これらは異なる概念です.ここでのスタックは、実際には(スタックの性質を満たす)優先キューのデータ構造を指し、1番目の要素が最も優先権を持っている.スタックは実際には先進的な後出の性質を満たす数学やデータ構造である.スタック、スタックという言い方はつながっているが、彼らには大きな違いがあり、つながっているのは歴史のせいだ.グローバル、静的、newで生成された変数はすべてスタックの中で動的に割り当てられた変数スタックの中で局所変数を割り当てスタックの中で関数の中で宣言した変数スタックの中でnewマーカーを使ってスタックの中でグローバル変数とstatic変数はすべてグローバルゾーンプログラムでスタック変数に動的メモリを割り当て、プログラムの終了時にスタック変数に割り当てられた空間は自動的に解放される.スタック変数に割り当てられたスペースは自動的に解放されません.プログラムにスタック変数が解放されていない場合は、システムメモリが消費されます.スタックは、「後進先出」アルゴリズムを実行するデータ構造です.
直径が大きくなく、一端が開口し、一端が閉鎖された竹筒が想定される.番号が書かれた小さなボールがいくつかあり、小さなボールの直径は竹筒の直径よりやや小さい.今、異なる番号のボールを竹筒の中に入れると、先に入れたボールは後に出すしかなく、逆に、後に入れたボールは先に出すことができるという法則が発見されます.だから「先進後出」はこのような構造の特徴です.
スタックはこのようなデータ構造です.メモリに記憶領域を開き、データが順番に格納される(すなわち「圧入-push」)領域です.最後のスタックに押し込まれたデータが存在するデータユニットを指すアドレスポインタがあり、このアドレスポインタを格納するレジスタをスタックインジケータと呼ぶ.データを入れ始めるセルを「スタックベース」といいます.データは一つ一つ格納され、このプロセスを「スタック」と呼ぶ.スタックを押す過程で、1つのデータがスタックに押し込まれるたびに、前のユニットに接続された後ろのユニットに配置され、スタックインジケータのアドレスが自動的に1加算されます.これらのデータを読み取る場合、スタックインジケータのアドレスに従ってデータを読み取ると、スタックインジケータのアドレス数が自動的に1減少します.このプロセスを「ポップアップ」と呼びます.これで後進先出の原則が実現した.
スタックはコンピュータで最もよく使われるデータ構造であり、例えば関数の呼び出しはコンピュータでスタックで実現される.スタックは配列で格納してもよいし、後で紹介するチェーンテーブルで格納してもよい.次に、スタックの構造体定義を示します.スタックトップポインタ、データアイテム配列が含まれます.スタックトップポインタが最初に-1を指し、データを格納すると、スタックトップポインタに1を加え、データを取り出した後、スタックトップポインタは1を減算します.
#define MAX_SIZE 100
typedef int DATA_TYPE;
struct stack
{
     
DATA_TYPE data[MAX_SIZE];
int top;
};