2

現在、 Expert C Programmingの第 6 章を読んでいて、データ セグメントのサイズに非常に興味があります。

データ セグメントの違いを確認するために 3 つのプログラムを作成しました。

私のプラットフォームは MacBook Pro、OS X 10.8 で、コマンドを使用しclang xxx.cてコードをコンパイルします。

int main()
{
    int i, j;
    return 0;
}

__テキスト 4096 __データ 0


int arr[10000];
int main()
{
    int i, j;
    return 0;
}

__テキスト 4096 __データ 40960


int main()
{
    int i, j;
    int arr[10000];
    return 0;
}

__テキスト 4096 __データ 4096

3つのサイズすべてが互いに異なるのはなぜですか?

4

3 に答える 3

4

プログラム ローダーを作成したり、組み込みシステムで作業している場合を除き、さまざまなセグメントを気にする必要はありません。

ただし、3 つの従来の標準セグメントは次のとおりです。

  • text、実際の実行可能コードを含む
  • 初期化されたデータ (初期化されたグローバル変数など) を含むdata 。
  • 初期化されていないデータを含むbss (初期化されていないグローバル変数など)

関数内でローカルな変数は、実行時にスタックに配置されるため、特定のセグメントはありません。

これらのセグメントは多くの場合、プラットフォームのページ サイズの倍数であり、i386 および派生物では 4096 バイトです。したがって、1 バイトだけが必要な場合でも、セグメント サイズは 4096 バイトに切り上げられます。2 番目の例では、40000 バイトのデータがあり、これは 40960 である 4096 の最も近い倍数に切り上げられます。

bssセグメントがある場合、その中のデータは多くの場合、プログラム ローダーによってゼロにされます。bssセグメントに関するもう 1 つの注意点は、実際にはオブジェクトまたは実行可能ファイルでスペースを使用しないことです。そのデータは初期化されていないため、サイズ以外はメモリに保存する必要はありません。

于 2013-01-15T07:05:48.983 に答える
1

テキスト セクションは、プログラム テキスト (またはコード) が存在する場所です。したがって、3 つの例で一定であることは理にかなっています。

最初の例では、グローバル変数も文字列リテラルもありません。したがって、データ サイズはゼロです。

2番目の例では、データセクションに入る〜40 Kのグローバルバッファがあります(実際には、初期化されていないため、おそらくBSSであり、実行可能ファイルには含まれていません。)

3 番目の例では、バッファは のスタックにありmain()ます。ただし、グローバル データを追加していないため、そのデータ サイズがゼロ以外である理由がよくわかりません。

多くの実行形式は、これらのセクション サイズをシステムの実行に便利なサイズに調整します。Intel x86 のページ サイズは 4KiB であるため、リンカがこれらのセクションを 4096 に合わせていると思われます。

于 2013-01-15T07:05:38.210 に答える
0

2番目の例では、配列は静的に初期化されます。つまり、プロセスの存続期間全体にわたって存在します。リンカーは、データ セクションに 10000 個の整数用のスペースを予約します。

3番目の例では、配列は関数のスタックに作成されます。つまり、最初は存在せ、プロセスが入った後にのみ初期化されます(これは「プロセスの完全な存続期間」とは異なります。の前にランタイム サポート コードが実行され、その後にクリーンアップ処理が実行されます)。リンカは何かのためにデータ セクションにスペースを確保し (何が何なのかよくわかりません)、残り (4096 から予約されたアイテムのサイズを差し引いたもの) は、セクションがページ整列されている (つまり、ページの倍数で割り当てられている) ことの効果です。サイズ、この場合は 4k)。main()main()main()

于 2013-01-15T07:04:57.507 に答える