C/C++スタックとスタックの紹介

3345 ワード

メモリパーティション
C/C++コンパイルされたプログラムが消費するメモリは、以下の部分に分けられます.
  • スタック領域(stack):コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.データ構造内のスタックと同様に動作します.
  • ヒープエリア(heap):一般的にプログラマによってリリースが割り当てられ、プログラマがリリースされない場合、プログラム終了時にOSによって回収される可能性があります.データ構造のスタックとは別のものであることに注意してください.割り当て方法はチェーンテーブルに似ています.
  • グローバル領域(静的領域、static):グローバル変数と静的変数の記憶はブロックに置かれ、初期化されたグローバル変数と静的変数はブロック領域にあり、初期化されていないグローバル変数と初期化されていない静的変数は隣接する別のブロック領域にある.プログラム終了後にシステムリリースがあります.
  • 文字定数領域:定数文字列はここにあり、プログラムが終了するとシステムから解放されます.
  • プログラムコード領域:関数体のバイナリコードを格納します.

  • 実例説明
    //main.cpp 
    int a = 0;//        
    char *p1; //        
    main() 
    { 
    int b; //  
    char s[] = "abc"; //  
    char *p2; //  
    char *p3 = "123456"; //123456    ,p3   。 
    static int c =0;//  (  )     
    p1 = (char *)malloc(10); 
    p2 = (char *)malloc(20); 
    //     10 20         。 
    strcpy(p1, "123456"); //123456     ,         p3    "123456"       。 
    }

    スタックとスタックの理論知識
    申請方式
    スタック:システムによって自動的に割り当てられます.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間を開きます
    スタック:プログラマが自分で申請し(malloc/newを使用して)、サイズを指定する必要があります.しかしポインタ自体は局所変数としてスタックに存在し,空間はスタックに存在する.
    申請後のシステムの応答
    スタック:スタックの残りの領域が申請された領域より大きい場合、システムはプログラムにメモリを提供します.そうしないと、例外プロンプトスタックがオーバーフローします.
    ヒープ:まずオペレーティングシステムに
    空きメモリアドレスを記録するチェーンテーブルは、システムがプログラムの申請を受け取ると、そのチェーンテーブルを遍歴し、申請空間よりも大きな最初の空間のスタックノードを探し、その後、そのノードを空きノードチェーンテーブルから削除し、そのノードの空間をプログラムに割り当てます.また、多くのシステムでは、このメモリ空間の最初のアドレスに今回の割り当てのサイズが記録されます.これにより、コード内のdelete文が本メモリ領域を正しく解放できます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.
    サイズの制限
    スタック:Windowsで、
    スタックは低アドレスに拡張されたデータ構造であり、連続したメモリの領域である.この言葉の意味は
    スタックトップのアドレスとスタックの最大容量はシステムで予め定められており、WINDOWSではスタックの大きさは2 M(1 Mということもあり、つまり1つのコンパイル時に決定される定数)であり、申請された空間がスタックの余剰空間を超えるとoverflowが提示される.したがって、スタックから得られる空間は小さい.
    ヒープ:
    スタックは高アドレスに拡張されたデータ構造であり、不連続なメモリ領域である.これは,システムがチェーンテーブルで格納する空きメモリアドレスであるため,当然不連続であり,チェーンテーブルの遍歴方向は低アドレスから高アドレスである.スタックのサイズは、コンピュータシステムで有効な仮想メモリに制限されます.このことから,スタックが得られる空間は比較的柔軟であり,比較的大きいことが分かる.
    申請効率
    スタックはシステムによって自動的に割り当てられ、速度が速い.しかし、プログラマーはコントロールできません.
    スタックはnewで割り当てるメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.
    コンテンツの保存
    スタック:関数呼び出し時に、最初にスタックに入ったのは主関数の次の命令(関数呼び出し文の次の実行可能文)のアドレスで、それから関数の各パラメータで、ほとんどのCコンパイラでは、パラメータは右から左へスタックに入って、それから関数数の中の局所変数です.静的変数はスタックに入らないことに注意してください.
    今回の関数呼び出しが終了すると、ローカル変数は先にスタックを出て、それからパラメータで、最後にスタックトップポインタは最も最初に保存されたアドレス、つまりメイン関数の次の命令を指し、プログラムはこの点から実行を継続します.
    ヒープ:通常、ヒープのヘッダにヒープのサイズを1バイトで格納します.スタックの具体的な内容はプログラマーが手配します.
    アクセスこうりつ
    char s1[] = "aaaaaaaaaaaaaaa";
    char *s2 = "bbbbbbbbbbbbbbbbb";
    s 1は、運転時刻に付与される.s 2はコンパイル時に決定される.
    しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.
    例:
    #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に基づいて文字を読み出すのは明らかに遅い.
    変換元:http://www.cnitblog.com/guopingleee/archive/2009/02/16/54599.html