.bssセグメントが必要なのはなぜですか?


120

私が知っているのは、グローバル変数と静的変数が.dataセグメントに格納され、初期化されていないデータが.bssセグメントにあることです。私が理解していないのは、初期化されていない変数専用のセグメントがあるのはなぜですか?初期化されていない変数に実行時に値が割り当てられている場合、変数はまだ.bssセグメントにのみ存在しますか?

次のプログラムで aは、.dataセグメントb内にあり、.bssセグメント内にあります。あれは正しいですか?私の理解が間違っている場合は親切に私を修正します。

#include <stdio.h>
#include <stdlib.h>

int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[20]; /* Uninitialized, so in the .bss and will not occupy space for 20 * sizeof (int) */

int main ()
{
   ;
}  

また、次のプログラムを検討してください、

#include <stdio.h>
#include <stdlib.h>
int var[10];  /* Uninitialized so in .bss */
int main ()
{
   var[0] = 20  /* **Initialized, where this 'var' will be ?** */
}

3
BSSはBetter Save Spaceとして読み取ることができます
smwikipedia 2018年

回答:


89

その理由は、プログラムのサイズを小さくするためです。Cプログラムが組み込みシステムで実行され、コードとすべての定数が実際のROM(フラッシュメモリ)に保存されていると想像してください。このようなシステムでは、main()が呼び出される前に、すべての静的ストレージ期間オブジェクトを設定するために、初期の「コピーダウン」を実行する必要があります。通常は次の擬似のようになります。

for(i=0; i<all_explicitly_initialized_objects; i++)
{
  .data[i] = init_value[i];
}

memset(.bss, 
       0, 
       all_implicitly_initialized_objects);

.dataと.bssはRAMに保存されますが、init_valueはROMに保存されます。それが1つのセグメントであった場合、ROMは多くのゼロで埋められ、ROMサイズが大幅に増加する必要がありました。

RAMベースの実行可能ファイルも同様に機能しますが、本当のROMはありません。

また、memsetは非常に効率的なインラインアセンブラである可能性が高いため、スタートアップコピーダウンをより高速に実行できます。


7
明確にするために:.dataと.bssの唯一の違いは、起動時に「コピーダウン」を順次実行できるため、より高速になるということです。それが2つのセグメントに分割されていない場合、初期化では、初期化されていない変数に属するRAMスポットをスキップする必要があるため、時間が無駄になります。
CL22 2013年

80

.bssセグメントは、最適化です。.bssセグメント全体は、実行中のプロセスでのサイズを示す単一の数値(おそらく4バイトまたは8バイト)で記述されますが、.dataセクションは初期化された変数のサイズの合計と同じ大きさです。したがって、.bssにより、実行可能ファイルのサイズが小さくなり、ロードが速くなります。それ以外の場合、変数は.data明示的にゼロに初期化されたセグメントにある可能性があります。プログラムは違いを見分けるのが難しいでしょう。(詳細には、のオブジェクトのアドレスは、.bssそれが.dataセグメント内にある場合、おそらくアドレスとは異なるでしょう。)

最初のプログラムでは、aであろう.dataセグメントとbであろう.bss実行可能ファイルのセグメント。プログラムが読み込まれると、区別は重要ではなくなります。実行時に、バイトbを占有し20 * sizeof(int)ます。

2番目のプログラムでvarは、スペースが割り当てられ、の割り当てmain()によってそのスペースが変更されます。たまたま、スペースvar.bssセグメントではなくセグメントに記述され.dataていたとしても、プログラムの実行時の動作には影響しません。


16
たとえば、初期化されていない多くのバッファを4096バイトの長さにすることを検討してください。これらの4kバッファーのすべてがバイナリーのサイズに寄与するようにしますか?それは多くの無駄なスペースになるでしょう。
Jeff Mercado

1
@jonathen killer:なぜbssセグメント全体が単一の数字で記述されるのですか?
Suraj Jain

@JonathanLefflerつまり、ゼロで初期化されたすべての静的変数はbssに入ります。それで、その値がゼロにならないようにしてください。また、なぜ.dataセクションにスペースが与えられていないのですか?
Suraj Jain

2
@SurajJain:格納される数は、ゼロで埋められるバイト数です。そのような初期化されていない変数がない限り、プログラムが読み込まれるとbssセクションのすべてのバイトがゼロになりますが、bssセクションの長さはゼロにはなりません。
ジョナサンレフラー

1
実行可能ファイルの.bssセクションは、単なる数値です。インメモリプロセスイメージの.bssセクションは、通常.dataセクションに隣接するメモリであり、多くの場合、ランタイム.dataセクションは.bssと結合されます。実行時メモリは区別されません。場合によっては、bssが始まった場所を見つけることができます(edata)。実際には、プロセスイメージが完了すると、.bssはメモリに存在しません。ゼロ化されたデータは.dataセクションの単純な部分です。しかし、詳細には、O / Sなどによって異なります
ジョナサン・レフラー

15

以下からのアセンブリ言語のステップバイステップ:Linuxでのプログラミングに関するジェフDuntemannことで、.DATAセクション:

.DATAセクションでは、初期化されたデータ項目のデータ定義が含まれています。初期化されたデータは、プログラムが実行を開始する前に値を持つデータです。これらの値は、実行可能ファイルの一部です。実行可能ファイルがメモリに読み込まれて実行されると、メモリに読み込まれます。

.dataセクションについて覚えておくべき重要なことは、定義する初期化されたデータ項目が多いほど、実行可能ファイルが大きくなり、実行時にディスクからメモリにロードするのに時間がかかることです。

および.bssセクション:

プログラムの実行を開始する前に、すべてのデータ項目に値が必要なわけではありません。たとえば、ディスクファイルからデータを読み取る場合、データがディスクから入って来た場所を確保する必要があります。このようなデータバッファーは、プログラムの.bssセクションで定義されています。バッファーにいくつかのバイト数を確保し、バッファーに名前を付けますが、バッファーに存在する値を指定しません。

.dataセクションで定義されたデータ項目と.bssセクションで定義されたデータ項目の間には決定的な違いがあります。.dataセクションのデータ項目は実行可能ファイルのサイズに追加されます。.bssセクションのデータ項目にはありません。16,000バイト(場合によってはそれ以上)を占めるバッファを.bssで定義し、実行可能ファイルのサイズにほとんど何も(説明では約50バイト)追加することができます。


9

さて、まず第一に、あなたの例のそれらの変数は初期化されていません。Cは、他の方法では初期化されない静的変数が0に初期化されることを指定します。

したがって、.bssの理由は、ローダーがディスクからデータをコピーする代わりにゼロの束を割り当てることができるため、実行可能ファイルが小さくなり、スペースが節約され、プログラムの読み込みが高速になるためです。

プログラムを実行すると、プログラムローダーは.dataと.bssをメモリにロードします。したがって、.dataまたは.bssにあるオブジェクトへの書き込みはメモリにのみ書き込まれ、ディスク上のバイナリにフラッシュされることはありません。


5

システムV ABI 4.1(1997)(AKA ELF仕様)も、答えは含まれています:

.bssこのセクションは、プログラムのメモリイメージに寄与する初期化されていないデータを保持します。定義により、システムはプログラムの実行が始まるとデータをゼロで初期化します。セクションタイプで示されるように、セクションはファイルスペースを占有しませんSHT_NOBITS

セクション名.bssは予約されており、特別な効果があると述べています。特に、ファイルスペースを占有しないため、に勝る利点があり.dataます。

もちろん、欠点は0、OSがメモリにバイトを配置するときにすべてのバイトを設定する必要があることです。

SHT_NOBITSセクションタイプのドキュメントでは、その肯定を繰り返し:

sh_sizeこのメンバーは、セクションのサイズをバイト単位で示します。セクションタイプがSHT_NOBITSでない限り、セクションsh_size はファイル内のバイトを占有します。タイプのセクションはSHT_NOBITSゼロ以外のサイズである可能性がありますが、ファイル内のスペースを占有していません。

C標準は、セクションについては何も言いませんが、我々は簡単に変数がでのLinuxに格納されている場所を確認することができるobjdumpreadelfし、初期化されていないグローバルが実際にに格納されていると結論します.bss。たとえば、この回答を参照してください:Cで宣言され、初期化されていない変数はどうなりますか?


3

Wikipediaの記事.bssは、1950年代半ば(イッピー、私の誕生日;-)からの用語であることから、素晴らしい歴史的説明を提供します。

昔は、すべてのものが貴重だったので、予約された空きスペースを通知する方法はどれも役に立ちました。これ(.bss)がスタックしています。

.dataセクションは空ではないスペース用であり、定義された値が入力されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.