コンピューティングにおいて、データ セグメント(多くの場合、.dataと表記) は、初期化された静的変数(つまり、グローバル変数と静的ローカル変数) を含むオブジェクト ファイルまたはプログラムの対応するアドレス空間の一部です。このセグメントのサイズは、プログラムのソース コード内の値のサイズによって決定され、実行時に変更されません。
データセグメントは読み取り/書き込み可能で、変数の値は実行時に変更される可能性があります。これは読み取り専用のデータセグメント(変数ではなく静的定数を含むコード セグメント(rodataセグメントまたは.rodataコード セグメント(テキスト セグメントとも呼ばれます) とは対照的です。初期化されていないデータ (変数と定数の両方) は、代わりにBSS セグメント。
歴史的に、内部アドレス レジスタのネイティブ サイズが許容するよりも大きなメモリ アドレス空間をサポートできるように、初期の CPU はセグメント化システムを実装し、特定の領域へのオフセットとして使用する小さなインデックス セットを保存していました。Intel 8086ファミリの CPU は、コード セグメント、データ セグメント、スタック セグメント、および追加セグメントの 4 つのセグメントを提供していました。各セグメントは、実行中のソフトウェアによってメモリ内の特定の場所に配置され、それらのセグメント内のデータを操作するすべての命令は、そのセグメントの開始を基準にして実行されました。これにより、通常は 64 KB のメモリ空間にアクセスできる 16 ビット アドレス レジスタが、1 MB のメモリ空間にアクセスできるようになりました。
メモリ空間を特定のタスクを持つ個別のブロックに分割するこの概念は、当時のプログラミング言語にも引き継がれ、その概念は現代のプログラミング言語でも広く使用されています。
プログラムメモリ
コンピュータ プログラム メモリは、読み取り専用と読み取り/書き込みの 2 つのセクションに大別できます。この区別は、マスク ROM、EPROM、PROM、EEPROMなどの読み取り専用メモリにメイン プログラムを保持していた初期のシステムから生まれました。システムが複雑になり、プログラムが ROM から実行されるのではなく、他のメディアから RAM にロードされるようになったため、プログラム メモリの一部を変更してはならないという考え方が維持されました。これらはプログラムの.textセグメントと.rodataセグメントになり、書き込み可能な残りの部分は特定のタスク用にいくつかの他のセグメントに分割されました。
コード
コードセグメント(テキスト セグメントとも呼ばれます)には実行可能コードが含まれており、通常は読み取り専用で固定サイズです。
データ

データセグメントには、初期化された静的変数 (つまり、定義された値を持ち変更可能なグローバル変数とローカル静的変数) が含まれます。C の例には次のものがあります。
int i = 3 ; char a [] = "Hello World" ; static int b = 2023 ; // 初期化された静的グローバル変数void foo ( void ) { static int c = 2023 ; // 初期化された静的ローカル変数}
BSSS について
BSSセグメントには、初期化されていない静的データ (変数と定数の両方) が含まれます。つまり、ゼロに初期化されているか、ソース コードで明示的に初期化されていないグローバル変数とローカル静的変数です。C の例を次に示します。
静的int i ;静的char a [ 12 ];
ヒープ
ヒープセグメントには動的に割り当てられたメモリが含まれ、通常は BSS セグメントの末尾から始まり、そこからより大きなアドレスに拡大します。これはmalloc、 calloc 、 realloc 、および free によって管理され、brkおよびsbrkシステム コールを使用してサイズを調整できます ( brk/sbrk と単一のヒープ セグメントの使用は、 malloc/calloc/realloc/free の契約を満たすために必須ではないことに注意してください。また、mmap /munmap を使用して実装し、プロセスの仮想アドレス空間に潜在的に連続していない仮想メモリ領域を予約/予約解除することもできます)。ヒープ セグメントは、プロセス内のすべてのスレッド、共有ライブラリ、および動的にロードされたモジュールによって共有されます。
スタック
スタックセグメントには、通常メモリの上位部分にあるLIFO構造のコール スタックが含まれます。「スタック ポインタ」レジスタはスタックの最上部を追跡し、値がスタックに「プッシュ」されるたびに調整されます。1 つの関数呼び出しに対してプッシュされる値のセットは、「スタック フレーム」と呼ばれます。スタック フレームは、少なくとも戻りアドレスで構成されます。自動変数もスタックに割り当てられます。
スタック セグメントは、従来ヒープ セグメントに隣接しており、互いに向かって成長していました。スタック ポインターがヒープ ポインターに出会うと、空きメモリが使い果たされました。大規模なアドレス空間と仮想メモリ技術では、スタック セグメントはより自由に配置される傾向がありますが、それでも通常は収束方向に成長します。標準の PC x86 アーキテクチャでは、スタックはアドレス 0 に向かって成長します。つまり、呼び出しチェーンのより深いところにある最近の項目は、数値的に低いアドレスにあり、ヒープに近いということです。他のアーキテクチャでは、スタックは反対方向に成長します。
通訳言語
インタプリタ型言語の中には、データセグメントに似た機能を提供するものもあり、特にPerl [1]やRuby がそうです。[2]__DATA__これらの言語では、 (Perl) または__END__(Ruby、旧Perl) の行を含めることで、コードセグメントの終了とデータセグメントの開始が示されます。この行より前のコンテンツのみが実行され、この行より後のソースファイルの内容は、PACKAGE::DATAPerl (例: main::DATA) やRuby ではファイルオブジェクトとして使用できます。これは、ヒアドキュメント(ファイルリテラル)
DATAの一種と考えることができます。
参照
参考文献
- ^ perldata: 特殊リテラル
- ^ ルビー: オブジェクト: __END__
外部リンク
- 「C スタートアップ」。bravegnu.org。
- 「mem_sequence.c - プロセス内のメモリ領域を順番にリストします」。2009 年 2 月 2 日にオリジナルからアーカイブされました。
- ファン・デル・リンデン、ピーター(1997)。エキスパート C プログラミング: ディープ C の秘密(PDF)。プレンティス・ホール。 119ページ以降。
