グローバル変数、ローカル変数、静的グローバル変数、静的ローカル変数のメモリ内の違い、スタックとスタックの違い
5299 ワード
コレクション変数、ローカル変数、静的グローバル変数、静的ローカル変数がメモリにどのように格納されるか、どのような違いがあるか、スタックとスタックの違いは、C/C++の基礎的な問題です.さまざまな採用筆記試験の面接では、それに関連する問題に直面することがよくあります.先日、それに関する文章をいくつか読みましたが、ここにまとめておきます.
まず、4つの変数の違いを分析します.
一、まずプログラムのメモリ分配から言えば、1つの完全なC/C++プログラムが実行時に占有するメモリはいくつかの部分に分けられる.
スタック(stack):コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.データ構造内のスタックと同様に動作します.
ヒープ(heap):一般的にプログラマーによってリリースが割り当てられ、プログラマーがリリースしない場合、プログラム終了時にOSによって回収される可能性があります.データ構造のスタックとは異なることに注意してください.割り当て方法はチェーンテーブルに似ています.mallocやnewなどの操作は実際にはスタックでメモリを申請し、オブジェクトが使用済みになったら手動で解放しなければならない.そうしないと、プログラムの終了時にシステムが回収するのを待つしかなく、メモリ漏れが発生する.
グローバル領域(静的領域):グローバル変数と静的変数は一緒に格納され、初期化されたグローバル変数と静的変数は同じ領域に格納され、初期化されていないグローバル変数と静的変数は隣接する領域に格納されます.この領域は、プログラムの終了後にシステムによって解放されます.
テキスト定数領域:定数文字列はここに保存され、プログラムが終了した後にシステムによって解放されます.文字定数はこのようなchar*str="abc";その中の「abc」.実際には、変数aとbが「abc」に割り当てられているなど、多重化され、実際には同じアドレスを指しています.
プログラムコード領域:関数体のバイナリコードを格納します.
二、次に例のプログラムを見ます.
メモリアドレスのスクリーンショットを添付し、主にp 1とp 3が指す「1234560」が同じ場所に最適化されているかどうかを検証します.
三、さらに役割ドメインから区別する.
グローバル変数にはグローバルな役割ドメインがあります.グローバル変数は、1つのソースファイルで定義するだけで、すべてのソースファイルに作用します.もちろん、グローバル変数定義を含まない他のソースファイルは、externキーでグローバル変数を再宣言する必要があります.
ローカル変数はローカル役割ドメインのみであり、自動オブジェクト(auto)であり、プログラム実行中は常に存在するのではなく、関数実行中にのみ存在し、関数の1回の呼び出し実行が終了すると、変数は取り消され、その使用メモリも回収される.
静的ローカル変数は、1回のみ初期化され、プログラムの実行が終了するまで初期化されたローカルドメインを有し、グローバル変数とは異なり、すべての関数に対してグローバル変数が表示され、静的ローカル変数は、定義された自己の関数体に対してのみ常に表示されます.
静的グローバル変数にもグローバル役割ドメインがあります.グローバル変数との違いは、プログラムが複数のファイルを含む場合、そのファイルを定義するのに役立ち、他のファイルには作用しません.つまりstaticキーワードで修飾された変数にはファイル役割ドメインがあります.これにより、2つの異なるソースファイルが同じ名前の静的グローバル変数を定義しても、それらは異なる変数です.
メモリ領域の割り当てから見ると、グローバル変数、静的ローカル変数、静的グローバル変数は静的ストレージ領域に空間を割り当て、ローカル変数はスタックに空間を割り当てます.
以上の解析から,局所変数を静的変数に変更すると,その記憶方式が変化し,生存期間が変化することが分かる.グローバル変数を静的変数に変更すると,その役割ドメインが変更され,その使用範囲が制限される.そのためstaticという説明子が異なる場所で果たす役割は異なる.
四、総じて言えば、グローバル変数、ローカル変数、静的グローバル変数、静的ローカル変数の違いは以下の通りである.
生存周期が違う作用範囲が異なる割り当て方法の違いスタックとスタックの違いを分析します.
割り当て方法の違いスペースサイズの違い分配効率が異なる破片を生成できるかどうか成長方向が異なる1、分配方式が違う:
スタック:システムによって自動的に割り当てられます.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間のスタックを開きます:プログラマーが自分で申請して、そして大きさを指定して、cの中でmalloc関数はp 1=(char*)malloc(10)のようです;C++では、p 2=(char*)new(10)のようなnew演算子を使用します.ただし、p 1、p 2自体はスタック内にあることに注意してください.
2、スペースの大きさが違う:
一般的に32ビットシステムでは、スタックメモリは4 Gの空間に達することができ、この観点からスタックメモリはほとんど制限されていない.しかし、スタックについては、一般に一定の空間サイズがあり、例えば、VC 6の下では、デフォルトのスタック空間サイズは1 Mである.
3、分配効率が違う:
スタックは機械システムが提供するデータ構造で、コンピュータは底層でスタックにサポートを提供します:専門のレジスタ格納スタックのアドレスを割り当てて、スタックを押してスタックを出してすべて専門の命令が実行して、これはスタックの効率が比較的に高いことを決定しました.スタックはC/C++関数ライブラリで提供され、そのメカニズムは複雑です.例えば、メモリを割り当てるために、ライブラリ関数は一定のアルゴリズム(具体的なアルゴリズムはデータ構造/オペレーティングシステムを参照できます)に従って、スタックメモリの中で利用可能な十分なサイズの空間を検索します.十分なサイズの空間がなければ(メモリの破片が多すぎるためかもしれません)、システム機能を呼び出してプログラムデータセグメントのメモリ領域を増やすことができ、十分なサイズのメモリに分けて返す機会があります.明らかに、スタックの効率はスタックよりずっと低い.
4、断片化問題:
スタック:スタックの残りの領域が申請された領域より大きい場合、システムはプログラムにメモリを提供します.そうしないと、例外プロンプトスタックがオーバーフローします.≪ヒープ|Heap|emdw≫:まず、オペレーティング・システムに空きメモリ・アドレスを記録するチェーン・テーブルがあることを知っておく必要があります.システムがプログラムの申請を受信すると、チェーン・テーブルを巡り、申請した空間よりも大きな最初の空間のヒープ・ノードを探します.その後、そのノードを空きノード・チェーン・テーブルから削除し、そのノードの空間をプログラムに割り当てます.また、ほとんどのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てのサイズが記録され、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.
スタックの場合、頻繁なnew/deleteはメモリ領域の不連続をもたらし、大量の破片をもたらし、プログラムの効率を低下させるに違いない.スタックにとって、この問題は存在しません.スタックは先進的な後出キューであるため、彼らはこのように対応しており、スタックの間からメモリブロックがポップアップすることは永遠に不可能です.彼がポップアップする前に、彼の上の後進的なスタックの内容がポップアップされています.
5、成長方向:
スタックにとって、成長方向は上向きであり、すなわちメモリアドレスが増加する方向である.スタックの場合、その成長方向は下向きであり、メモリアドレスが減少する方向に成長します.
スタックはスタックに比べてnew/deleteの使用が多いため、メモリの破片が大量に発生しやすい.専門的なシステムサポートがないため、効率が低い.ユーザ状態とコア状態の切り替えを引き起こす可能性があるため、メモリの申請は、より高価になります.したがって、スタックはプログラムの中で最も広く応用されており、関数の呼び出しでもスタックを利用して完了し、関数呼び出し中のパラメータ、戻りアドレス、EBP、ローカル変数はスタック方式で保存されている.だから、スタックではなくスタックを使うことをお勧めします.スタックには多くのメリットがありますが、スタックに比べてそれほど柔軟ではないため、大量のメモリスペースを割り当てる場合があります.スタックを使うほうがいいです.
http://codeup.org/archives/200
まず、4つの変数の違いを分析します.
一、まずプログラムのメモリ分配から言えば、1つの完全なC/C++プログラムが実行時に占有するメモリはいくつかの部分に分けられる.
スタック(stack):コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.データ構造内のスタックと同様に動作します.
ヒープ(heap):一般的にプログラマーによってリリースが割り当てられ、プログラマーがリリースしない場合、プログラム終了時にOSによって回収される可能性があります.データ構造のスタックとは異なることに注意してください.割り当て方法はチェーンテーブルに似ています.mallocやnewなどの操作は実際にはスタックでメモリを申請し、オブジェクトが使用済みになったら手動で解放しなければならない.そうしないと、プログラムの終了時にシステムが回収するのを待つしかなく、メモリ漏れが発生する.
グローバル領域(静的領域):グローバル変数と静的変数は一緒に格納され、初期化されたグローバル変数と静的変数は同じ領域に格納され、初期化されていないグローバル変数と静的変数は隣接する領域に格納されます.この領域は、プログラムの終了後にシステムによって解放されます.
テキスト定数領域:定数文字列はここに保存され、プログラムが終了した後にシステムによって解放されます.文字定数はこのようなchar*str="abc";その中の「abc」.実際には、変数aとbが「abc」に割り当てられているなど、多重化され、実際には同じアドレスを指しています.
プログラムコード領域:関数体のバイナリコードを格納します.
二、次に例のプログラムを見ます.
#include <iostream>
using
namespace
std;
int
a = 0;
//
char
*p1;
//
int
main()
{
int
b;
//
char
s[] =
"abc"
;
//
char
*p2;
//
char
*p3 =
"123456"
;
//p3 ,"123456\0"
static
int
c = 0;
// ( )
p1 = (
char
*)
malloc
(10);
p2 = (
char
*)
malloc
(20);
p1 =
"123456"
;
//"123456\0" , p1 p3 "123456\0" 。
return
0;
}
メモリアドレスのスクリーンショットを添付し、主にp 1とp 3が指す「1234560」が同じ場所に最適化されているかどうかを検証します.
三、さらに役割ドメインから区別する.
グローバル変数にはグローバルな役割ドメインがあります.グローバル変数は、1つのソースファイルで定義するだけで、すべてのソースファイルに作用します.もちろん、グローバル変数定義を含まない他のソースファイルは、externキーでグローバル変数を再宣言する必要があります.
ローカル変数はローカル役割ドメインのみであり、自動オブジェクト(auto)であり、プログラム実行中は常に存在するのではなく、関数実行中にのみ存在し、関数の1回の呼び出し実行が終了すると、変数は取り消され、その使用メモリも回収される.
静的ローカル変数は、1回のみ初期化され、プログラムの実行が終了するまで初期化されたローカルドメインを有し、グローバル変数とは異なり、すべての関数に対してグローバル変数が表示され、静的ローカル変数は、定義された自己の関数体に対してのみ常に表示されます.
静的グローバル変数にもグローバル役割ドメインがあります.グローバル変数との違いは、プログラムが複数のファイルを含む場合、そのファイルを定義するのに役立ち、他のファイルには作用しません.つまりstaticキーワードで修飾された変数にはファイル役割ドメインがあります.これにより、2つの異なるソースファイルが同じ名前の静的グローバル変数を定義しても、それらは異なる変数です.
メモリ領域の割り当てから見ると、グローバル変数、静的ローカル変数、静的グローバル変数は静的ストレージ領域に空間を割り当て、ローカル変数はスタックに空間を割り当てます.
以上の解析から,局所変数を静的変数に変更すると,その記憶方式が変化し,生存期間が変化することが分かる.グローバル変数を静的変数に変更すると,その役割ドメインが変更され,その使用範囲が制限される.そのためstaticという説明子が異なる場所で果たす役割は異なる.
四、総じて言えば、グローバル変数、ローカル変数、静的グローバル変数、静的ローカル変数の違いは以下の通りである.
生存周期が違う作用範囲が異なる割り当て方法の違いスタックとスタックの違いを分析します.
割り当て方法の違いスペースサイズの違い分配効率が異なる破片を生成できるかどうか成長方向が異なる1、分配方式が違う:
スタック:システムによって自動的に割り当てられます.例えば、関数内の局所変数int bを宣言する.システムは自動的にスタックの中でbのために空間のスタックを開きます:プログラマーが自分で申請して、そして大きさを指定して、cの中でmalloc関数はp 1=(char*)malloc(10)のようです;C++では、p 2=(char*)new(10)のようなnew演算子を使用します.ただし、p 1、p 2自体はスタック内にあることに注意してください.
2、スペースの大きさが違う:
一般的に32ビットシステムでは、スタックメモリは4 Gの空間に達することができ、この観点からスタックメモリはほとんど制限されていない.しかし、スタックについては、一般に一定の空間サイズがあり、例えば、VC 6の下では、デフォルトのスタック空間サイズは1 Mである.
3、分配効率が違う:
スタックは機械システムが提供するデータ構造で、コンピュータは底層でスタックにサポートを提供します:専門のレジスタ格納スタックのアドレスを割り当てて、スタックを押してスタックを出してすべて専門の命令が実行して、これはスタックの効率が比較的に高いことを決定しました.スタックはC/C++関数ライブラリで提供され、そのメカニズムは複雑です.例えば、メモリを割り当てるために、ライブラリ関数は一定のアルゴリズム(具体的なアルゴリズムはデータ構造/オペレーティングシステムを参照できます)に従って、スタックメモリの中で利用可能な十分なサイズの空間を検索します.十分なサイズの空間がなければ(メモリの破片が多すぎるためかもしれません)、システム機能を呼び出してプログラムデータセグメントのメモリ領域を増やすことができ、十分なサイズのメモリに分けて返す機会があります.明らかに、スタックの効率はスタックよりずっと低い.
4、断片化問題:
スタック:スタックの残りの領域が申請された領域より大きい場合、システムはプログラムにメモリを提供します.そうしないと、例外プロンプトスタックがオーバーフローします.≪ヒープ|Heap|emdw≫:まず、オペレーティング・システムに空きメモリ・アドレスを記録するチェーン・テーブルがあることを知っておく必要があります.システムがプログラムの申請を受信すると、チェーン・テーブルを巡り、申請した空間よりも大きな最初の空間のヒープ・ノードを探します.その後、そのノードを空きノード・チェーン・テーブルから削除し、そのノードの空間をプログラムに割り当てます.また、ほとんどのシステムでは、このメモリ領域の最初のアドレスに今回の割り当てのサイズが記録され、コードのdelete文がこのメモリ領域を正しく解放することができます.また,見つかったスタックポイントの大きさが申請の大きさに等しいとは限らないため,余分な部分を自動的に空きチェーンテーブルに再配置する.
スタックの場合、頻繁なnew/deleteはメモリ領域の不連続をもたらし、大量の破片をもたらし、プログラムの効率を低下させるに違いない.スタックにとって、この問題は存在しません.スタックは先進的な後出キューであるため、彼らはこのように対応しており、スタックの間からメモリブロックがポップアップすることは永遠に不可能です.彼がポップアップする前に、彼の上の後進的なスタックの内容がポップアップされています.
5、成長方向:
スタックにとって、成長方向は上向きであり、すなわちメモリアドレスが増加する方向である.スタックの場合、その成長方向は下向きであり、メモリアドレスが減少する方向に成長します.
スタックはスタックに比べてnew/deleteの使用が多いため、メモリの破片が大量に発生しやすい.専門的なシステムサポートがないため、効率が低い.ユーザ状態とコア状態の切り替えを引き起こす可能性があるため、メモリの申請は、より高価になります.したがって、スタックはプログラムの中で最も広く応用されており、関数の呼び出しでもスタックを利用して完了し、関数呼び出し中のパラメータ、戻りアドレス、EBP、ローカル変数はスタック方式で保存されている.だから、スタックではなくスタックを使うことをお勧めします.スタックには多くのメリットがありますが、スタックに比べてそれほど柔軟ではないため、大量のメモリスペースを割り当てる場合があります.スタックを使うほうがいいです.
http://codeup.org/archives/200