http://bellard.org/mersenne.htmlのプログラムの場合、GCCは最大130MBの実行可能ファイルを生成します。なんで?
1 に答える
*executable** のサイズを7.3 Kに変更t[1<<25]={2}
してみてください。(言うまでもなく、正しい結果は得られません)t[1<<25]
だけだったらt[1<<25]
、まったくスペースを取りませんでした。
ここでの問題は、配列が初期化されていること (最初の要素 = 2、次の 2^25-1 要素はすべて 0) であり、グローバル配列は初期化されているという理由だけでデータ セグメントに配置されます。
2 つのバージョンのアセンブリを生成し、違いを調べると、さらに明確になります。
[axiom@axiom ~]$ diff without_mem.s with_mem.s
15c15,21
< .comm t,134217728,32
---
> .globl t
> .align 32
> .type t, @object
> .size t, 134217728
> t: ***<- HERE!***
> .long 2
> .zero 134217724
お気づきのように、元のバージョンでは、アセンブラはデータ セグメントで 2^27 (134217728) バイトを生成するように指示されています。したがって、オブジェクトファイル自体の一部になります。( switch でコンパイルすることでアセンブリを生成できます-S
gcc -S -fverbose-asm t1.c
)
しかし、なぜ 129 MB なのですか?
1<< n= 2^n (1 を n 回左にシフト)。 => 1<<25=2^25. 現在 1 整数 = 4 バイト = 2^2 バイト => 2^25 整数=2^27 バイト=2^7 * 1 M バイト= 128 MB
詳細については、次を参照してください。
※注1:厳密にはオブジェクトファイルです。
注2:コメントで指摘されているように、実行可能ファイルが7.3Kであっても、プロセス(実行中のプログラム)の合計サイズは129Mbになることにも注意してください。(メモリは、プログラムの実行が開始されると割り当てられます)。コマンドを使用して、プログラムのメモリ使用量を確認できますtop
。
注 3: t がグローバルであるという理由だけでこれが成立することを強調する価値があります。関数にローカルなデータの割り当ては、実行時にスタック上で行われます。したがって、t
ローカルの場合、オブジェクト ファイルは 7.3K しか使用しません。
注 4: 初期化static
されたグローバル変数と同様に、初期化されたローカル変数もdata
セグメントに保持されます。static
グローバルは、変数のスコープを現在のファイルのみに制限していることを除いて、グローバルと同じです。