Linux Cスタックとスタックの違い


一、予備知識——プログラムのメモリ配分
C/C++コンパイルされたプログラムが消費するメモリは、以下の部分に分けられます.
1、スタック領域(stack)-コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.その動作は、データ構造内のスタックに似ています.
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    ,p3   。
    static int c =0; //  (  )    
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20); //     10 20         。
    strcpy(p1, "123456"); //123456     ,         p3    "123456"       。
}


二、スタックとスタックの理論知識2.1申請方式
スタック:
システムによって自動的に割り当てられます.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間を開く.
ヒープ(heap):
ユーザーが申請し、サイズを指定し、cでmalloc関数
例えばp 1=(char*)malloc(10);
C++でnew演算子を使う
例えばp 2=(char*)new(10);
しかし、p 1、p 2自体はスタックにあり、それらが指す空間はスタックにあることに注意してください.
2.2申請後のシステムの応答
スタック(stack):スタックの残りの領域が申請された領域より大きい場合、システムはプログラムにメモリを提供します.そうしないと、例外プロンプトスタックがオーバーフローします.
ヒープ(heap):まず、オペレーティングシステムに空きメモリアドレスを記録するチェーンテーブルがあることを知っておく必要があります.システムがプログラムの申請を受け取ると、そのチェーンテーブルを遍歴し、申請した空間よりも大きな最初の空間のヒープノードを探し、その後、そのノードを空きノードチェーンテーブルから削除し、そのノードの空間をプログラムに割り当てます.また、多くのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てのサイズが記録され、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.
2.3申請サイズの制限
スタック(stack):Windowsでは、スタックは低アドレスに拡張されたデータ構造であり、連続したメモリの領域である.スタックトップのアドレスとスタックの最大容量はシステムで予め定められており、WINDOWSではスタックの大きさは2 M(1 Mということもあり、つまり1つのコンパイル時に決定される定数)であり、申請された空間がスタックの残りの空間を超えるとoverflowが提示される.したがって、スタックから得られる空間は小さい.
スタック(heap):スタックは高アドレスに拡張されたデータ構造であり、不連続なメモリ領域である.これは,システムがチェーンテーブルで格納する空きメモリアドレスであるため,当然不連続であり,チェーンテーブルの遍歴方向は低アドレスから高アドレスである.スタックのサイズは、コンピュータシステムで有効な仮想メモリに制限されます.このことから,スタックが得られる空間は比較的柔軟であり,比較的大きいことが分かる.
2.4申請効率の比較:
スタック(stack):システムによって自動的に割り当てられ、速度は速いが、プログラマーは制御できない.
ヒープ(heap):newで割り当てるメモリで、一般的に速度が遅く、メモリの破片が発生しやすいが、最も使いやすい.
また、WINDOWSでは、VirtualAllocでメモリを割り当てるのが一番です.スタックではなく、スタックではなく、プロセスのアドレス空間に直接高速メモリを残すのではなく、最も使いにくいです.しかし、スピードが速く、最も柔軟です.
2.5スタックおよびスタック内のストレージ
スタック(stack):関数呼び出し時に、最初にスタックに入ったのは、主関数の次の命令(関数呼び出し文の次の実行可能文)のアドレスであり、関数の各パラメータであり、ほとんどのCコンパイラでは、パラメータは右から左へスタックに入り、関数のローカル変数である.静的変数はスタックに入らないことに注意してください.
今回の関数呼び出しが終了すると、ローカル変数は先にスタックを出て、それからパラメータで、最後にスタックトップポインタは最も最初に保存されたアドレス、つまりメイン関数の次の命令を指し、プログラムはこの点から実行を継続します.
スタック(heap):スタックのヘッダにスタックのサイズを1バイトで格納するのが一般的です.スタックの具体的な内容はプログラマーが手配します.
2.6アクセス効率の比較
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbはコンパイル時に確定した.
しかしながら、以降のアクセスでは、スタック上の配列はポインタが指す文字列(例えばスタック)よりも速い.
例:
#include <stdio.h>
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まとめ:
スタックとスタックの違いは、次のような比喩で見ることができます.
宿を使うのは私たちがレストランで食事をするのと同じで、料理を注文して(申請を出して)、お金を払って、食べて(使用して)、満腹になったら行って、野菜を切って、料理を洗うなどの準備と茶碗を洗って、鍋を洗うなどの掃除の仕事を気にする必要はありません.彼のメリットは速いですが、自由度は小さいです.
山を使うのは自分で好きな料理を作るようなもので、面倒ですが、自分の好みに合っていて、自由度が高いです.
スタックとスタックの主な違い:オペレーティングシステムのスタックとスタックは、上記のように、多くは言いません.
また、データ構造のスタックとスタックもあり、これらは異なる概念です.ここでのスタックは、実際には(スタックの性質を満たす)優先キューのデータ構造を指し、1番目の要素が最も優先権を持っている.スタックは実際には先進的な後出の性質を満たす数学やデータ構造である.
スタック、スタックという言い方はつながっているが、彼らには大きな違いがあり、つながっているのは歴史のせいだ.
三、スタックとスタックの主な違い
前述したように、スタックはコンパイラによって必要に応じて割り当てられ、必要でない場合に自動的に消去される変数ストレージ領域です.中の変数は通常局所変数、関数パラメータなどです.スタックはmalloc()関数(C++言語はnew演算子)によって割り当てられたメモリブロックであり、メモリ解放はプログラマによって手動で制御され、C言語ではfree関数で完了する(C++ではdelete).
スタックとスタックの主な違いは以下の点です.
(1)管理方式が異なる
スタックはコンパイラによって自動的に管理され、プログラマーの手動制御を必要としない.
スタックスペースの申請解放作業はプログラマーが制御し、メモリ漏れが発生しやすい. 
(2)空間の大きさが異なる
スタックは低アドレスに拡張されたデータ構造であり、連続したメモリ領域である.スタックトップのアドレスとスタックの最大容量はシステムが予め規定しており、申請された空間がスタックの残りの空間を超えると、プロンプトがオーバーフローすることを意味する.したがって、ユーザがスタックから得ることができる空間は小さい. 
スタックは高アドレスに拡張されたデータ構造であり、不連続なメモリ領域である.システムは空きメモリアドレスをチェーンテーブルで格納し、チェーンテーブルの遍歴方向は低アドレスから高アドレスに向かうためである.このことから,スタックが得られる空間は柔軟であり,大きいことがわかる.スタック内の要素はすべて1つ1つ対応しており、スタックの間からメモリブロックがポップアップされることはありません. 
(3)断片化の有無
スタックの場合、頻繁なmalloc/free(new/delete)はメモリ領域の不連続をもたらし、大量のフラグメントをもたらし、プログラムの効率を低下させる必要があります(プログラムは終了後、オペレーティングシステムがメモリを回収管理しますが).スタックにとって、この問題は存在しません. 
(4)成長方向が異なる
スタックの成長方向は上向きであり、すなわちメモリアドレスが増加する方向である.
スタックの成長方向は下向き、すなわちメモリアドレスが減少する方向である. 
(5)分配方式が異なる
スタックは、プログラム内でmalloc()関数によって動的に割り当てられ、free()関数によって解放される.
スタックの割り当てと解放はコンパイラによって行われ、スタックの動的割り当てはalloca()関数によって行われるが、スタックの動的割り当てとスタックは異なり、彼の動的割り当てはコンパイラによって申請され、解放され、手作業で実現する必要はない.
(6)分配効率が異なる
スタックは機械システムが提供するデータ構造であり、コンピュータは底層でスタックにサポートを提供する:専門のレジスタ格納スタックのアドレスを割り当て、スタックを押し出すには専門の命令が実行される.スタックはC関数ライブラリによって提供され、そのメカニズムは複雑で、例えばメモリを割り当てるために、ライブラリ関数は一定のアルゴリズム(具体的なアルゴリズムはデータ構造/オペレーティングシステムを参照することができる)に従ってスタックメモリの中で利用可能な十分な空間を検索します.例えば、十分な空間がない(メモリの破片が多すぎるためかもしれません).メモリ領域を再整理するためにオペレーティングシステムが必要になり、十分なサイズのメモリを分割して返す機会があります.明らかに、スタックの効率はスタックよりずっと低い.