8

C の学習中にいくつかの実験を行っていると、奇妙なことに出くわしました。これは私のプログラムです:

int main(void) {sleep(5);}

コンパイルすると、実行可能ファイルのサイズは 8496 バイトになります (26 バイトのソースと比較して!) これは、実行可能ファイルにスリープが呼び出され、呼び出すための命令が記述されているため理解できます。もう 1 つの注意点は、スリープがないと、実行可能ファイルが 4312 バイトになることです。

int main(void) {}

私の主な質問は、最初のプログラムが実行されたときに何が起こるかです。私は clang を使用してコンパイルし、Mac OS X を使用して実行しています。その結果 (Activity Monitor によると)、プログラムは 504KB の「実メモリ」を使用します。プログラムがわずか 4KB なのになぜこんなに大きいのですか? 実行可能ファイルがメモリにロードされていると想定していますが、スリープ コール以外は何もしていません。プログラムが 5 秒間スリープするのに 500KB が必要なのはなぜですか?

ちなみに私がスリープを使っているのは、そもそもActivity Monitorを使ってメモリの使用量を把握できるようにするためです。

単純な好奇心からお願いします、乾杯!

4

2 に答える 2

2

この場合、あなたが観察したサイズの違いは、動的リンクによって大きく引き起こされていると思います。

通常、リンカは共通コードを実行可能バイナリに配置しません。代わりに情報を予約し、バイナリがロードされるときにコードがロードされます。これらの共通コードは、shared object(SO)またはと呼ばれるファイルに保存されますdynamically linked library(DLL)

[pengyu@GLaDOS temp]$ cat test.c
int main(void) {sleep(5);}
[pengyu@GLaDOS temp]$ gcc test.c
[pengyu@GLaDOS temp]$ du -h --apparent-size a.out
6.6K    a.out
[pengyu@GLaDOS temp]$ gcc test.c -static
[pengyu@GLaDOS temp]$ du -h --apparent-size a.out
807K    a.out

また、ここでは、プロセスのメモリにあるものをリストしています。

  • ロードするために必要な動的ライブラリがあります。

    ここでlddは、バイナリの呼び出し時に動的ライブラリがロードされる結果を示します。mmapこれらのライブラリは、システムコールを呼び出して取得した部分にあります。

    [pengyu@GLaDOS temp]$ cat test.c
    int main(void) {sleep(5);}
    [pengyu@GLaDOS temp]$ gcc test.c
    [pengyu@GLaDOS temp]$ ldd ./a.out
    linux-vdso.so.1 (0x00007fff576df000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f547a212000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f547a5bd000)
    
  • のようなセクションがあり.data.codeバイナリ ファイルからのデータに割り当てられます。

    この部分はバイナリ実行可能ファイルに存在するため、サイズはファイル自体よりも大きくないと想定されています。実行可能バイナリの読み込み段階でコピーされるコンテンツ。

  • .bssプログラムの実行中に動的に使用するために割り当てられるスタックゾーンのようなセクションもあります。

    この部分はバイナリ実行可能ファイルには存在しないため、ファイル自体のサイズに影響されずにサイズが非常に大きくなる可能性があります。

于 2013-10-14T10:19:49.570 に答える