上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
 
組み込み系の開発なんかをしていると、グローバル変数や静的変数なんかを使用する場合に、初期値を代入しないようにしてくれと言われることがあります。
最初なんでなのかわからず理由を聞いたのですが、それを言ってきた人もよくわかっていないようで・・・
しかし、ネタ元はかなりプログラムができる人のようなので、あながち迷信とも思えず、しょうがないので考えてみました。


定義時に初期化していない静的な変数は.bssセクションに配置され、使用前(領域確保時?)に0初期化されます。
そして、定義時に初期化されている静的な変数は.dataセクションに配置され、使用前に.dataセクションに書き込まれている値で初期化されます。
また、初期化値が初期化対象のサイズより少ない場合は、初期化対象の空き領域には0が配置されます。

実行ファイルサイズの観点でまとめると。
.bssに配置すると.dataの初期化データが必要ないので実行ファイルサイズが小さくなります。
しかし、コード中で初期化が必要になる場合、.textセクションが増えるのでその分実行ファイルサイズが大きくなります。
また、リテラル文字列等をコードの初期化処理に使用する場合、.rodataも増大してしまいます。

初期化速度の観点でまとめると。
.bssの0初期化はmemset等で行われるので.dataセクションの初期化値ロード(ファイルリード)より高速。
しかし、コード中で初期化が必要になる場合、コードのロード及びロードしたルーチンの実行が必要なので、その分遅くなります。

これを踏まえて、ケーススタディとして、
グローバルの配列をリテラル文字列で初期化する場合を考えると、

○定義時代入の場合
・グローバル配列の領域を確保。
・.dataセクションからグローバル配列にデータロード(ファイル→メモリ)

○定義時未初期化でコード中でstrcpyの場合
・グローバル配列の領域及びリテラル文字列の領域を確保。
・グローバル配列を0初期化(レジスタ→メモリ)
・.rodataセクションからリテラル文字列領域にデータロード(ファイル→メモリ)
・リテラル文字列領域からグローバル配列にコピー(メモリ→メモリ)

後者の方が圧倒的に無駄ですので、この場合は定義時代入してしまうほうが良いです。

しかし、グローバル配列サイズ>リテラル文字列サイズの場合、
.dataセクションに余分な0が存在することになり、
この0の数によっては後者の方が早くなる状況も考えられます。

また、初期化に使用する文字列リテラルを他にも使用する場合、
.rodataのロードは無駄にならないので後者の方が良い場合も考えられます。

まとめ
どっちが良いかは状況によります。
実行環境のリソースが豊富な場合には、見やすい方で書くのをお勧めします。

補足1
定義時に0値代入した場合、被代入変数が.dataに配置されるか.bssに配置されるかは、
コンパイラの処理次第になります。
ちなみに新目のgccなんかは.bssに配置されるようになっています。

補足2
組み込み用のOSなんかでは、稀に.bssセクションの0初期化が省かれている場合があるそうです。
この場合、定義時に0値代入していたとしても実行時には不定値が入っていたりします。
 

<< 乱戦専用破壊特化甲刀 | Home | 伊藤悠の連載がビックコミックスピリッツでやってますのね >>

コメント

何わけのわからん記事書き連ねとんじゃ!!
死ね!!

Re: タイトルなし

ごめんね

コメントの投稿

URL:
Comment:
Pass:
秘密: 管理者にだけ表示を許可する
 

トラックバック


この記事にトラックバックする(FC2ブログユーザー)


 BLOG TOP 


template and material by HPテンプレート素材集IFD
  1. 無料アクセス解析
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。