3

グローバル変数があると、実行可能ファイルのサイズが大きくなりますか?はいの場合、どのように?データセクションのサイズだけを増やすのですか、それともテキストセクションのサイズを増やすのですか?

以下のようにグローバル変数と初期化がある場合:

char g_glbarr[1024] = {"jhgdasdghaKJSDGksgJKASDGHKDGAJKsdghkajdgaDGKAjdghaJKSDGHAjksdghJKDG"};

さて、これはデータセクションに1024を追加し、テキストセクションに初期化文字列のサイズを追加しますか?

代わりに、この配列に静的にスペースを割り当てる場合、それをmallocしてから、memcpyを実行すると、データセクションのサイズのみが減少するか、テキストセクションのサイズも減少しますか?

4

4 に答える 4

6

はい、そうです。基本的に、コンパイラはそれらをデータセグメントに格納します。コードで定数char配列を使用すると(のようにprintf("<1024 char array goes here");)、データセグメントに移動することがあります(一部の古いコンパイラ/ Borland?/はテキストセグメントに格納する場合があります)。コンパイラにグローバル変数をカスタムセクションに配置するように強制できます(VC ++の場合はそうでした#pragma data_seg(<segment name>))。

動的メモリ割り当ては、ヒープにメモリを割り当てるため、データ/テキストセグメントには影響しません。

于 2010-12-04T08:49:49.037 に答える
3

答えは実装に依存しますが、正常な実装の場合、これは静的ストレージ期間(グローバルまたはその他)の変数に対してどのように機能するかです。

  • 変数が初期化されるたびに、オブジェクトの初期化された値全体が実行可能ファイルに保存されます。これは、最初の部分だけが明示的に初期化されている場合でも当てはまります(残りは暗黙的にゼロです)。
  • 変数が定数で初期化されている場合、それは「テキスト」セグメントまたは同等のものになります。一部のシステム(最新のELFベース、おそらくWindowsも?)には、読み取り専用データ用の個別の「rodata」セグメントがあり、プログラムコードとは別に、実行不可としてマークすることができます。
  • 一定でない初期化変数は、実行可能ファイルの「データ」セグメントにあり、プログラムのロード時にオペレーティングシステムによってコピーオンライトモードでメモリにマップされます。
  • 初期化されていない変数(標準では暗黙的にゼロ)には、実行可能ファイル自体にストレージが予約されていませんが、オペレーティングシステムによってプログラムのロード時に作成される「bss」セグメントのサイズとオフセットがあります。
  • このような初期化されていない変数は、修飾されている場合、別の読み取り専用の「bss」のようなセグメントに作成される可能性constがあります。
于 2010-12-04T15:55:34.333 に答える
2

私は専門家として話しているわけではありませんが、プログラムにその壮大な文字列リテラルを含めるだけで、実行可能ファイルのサイズが大きくなると思います。文字列リテラルはどこかに格納する必要があるため、その文字列リテラルで何をするかは重要ではありません。

実行可能ファイルのどの「セクション」を増やすことが重要なのはなぜですか?これは修辞的な質問ではありません!

于 2010-12-04T08:40:45.187 に答える
1

答えは実装に少し敏感ですが、一般的には違います。あなたは本当に、またはアドレスg_glbarrへのポインタです。char文字列自体は定数文字列とともにデータセクションに配置され、g_glbarrコンパイル時に文字列のアドレスのシンボルになります。ポインタにスペースを割り当てることはなく、コンパイラはリンク時にアドレスを解決するだけです。

アップデート

@ジェイ、それはちょっと同じです。整数は(通常は)インラインです。コンパイラは、定数をコードに入れるだけにできるだけ近づきます。これは、ほとんどの通常のアーキテクチャでは、即時データから簡単に実行できる一般的なケースだからです。文字列定数は、引き続き一部の読み取り専用データセクションにあります。だからあなたが次のようなものを作るとき:

// warning: I haven't compiled this and wouldn't normally
// do it quite this way so I'm not positive this is
// completely grammatical C
struct X {int a; char * b; } x = { 1, "Hello" } ; 

1「即時」データになり、"Hello"は読み取り専用データのどこかに割り当てられ、コンパイラは次のような読み取り/書き込みデータを割り当てるものを生成します。

x:
x.a:   WORD    1
x.b    WORD    @STR42

ここで、はメモリ内STR42の文字列の場所の記号名です。"Hello"次に、すべてがリンクされると、@STR42はメモリ内の文字列の実際の仮想アドレスに置き換えられます。

于 2010-12-04T08:52:20.457 に答える