データ領域(.data)とBSS領域(.bss)の違いとは?ROMとRAMの関係を実務目線で解説

目次

データ領域(.data)とBSS領域(.bss)の違い(概要)

項目データ領域(.data)BSS領域(.bss)
初期値ありなし
RAM配置されるされる
ROM保存するしない
起動処理コピーゼロクリア
主な影響ROM消費RAM消費

データ領域(.data)とBSS領域(.bss)の違いは、初期値の有無です。
data領域は初期値あり、bss領域は初期値なしの変数が配置されます。

またデータ領域 と BSS領域 はどちらもRAMに配置されます。
違いは、初期値をROMからコピーするか、ゼロクリアするかです。

メモリ領域解説シリーズ

本記事は「メモリ領域解説」シリーズの1つです。

メモリ領域解説シリーズの全体像はこちら

組み込み開発でメモリレイアウトを理解するうえで避けて通れないのが「データ領域」と「BSS領域」です。

データ領域とBSS領域は、以下のようにRAMに配置されています。

メモリ領域の全体像

どちらもRAMに配置されるグローバル変数の領域ですが、役割はまったく異なります。

この記事では、

  • データ領域(.data)とは何か
  • BSS領域(.bss)とは何か
  • なぜわざわざ分かれているのか
  • 実務でどこを見るべきか

を、起動処理レベルまで踏み込んで解説します。

データ領域とBSS領域を含むメモリ領域の全体像についてはこちらの記事で解説しています。

初心者さん

.data領域と.bss領域って、どちらもグローバル変数が入る領域ですよね?何が違うんですか?

エンジニアくん

一番大きな違いは、初期値があるかどうかなんだ。
初期値がある変数は.data領域、 ない変数は .bss領域 に配置されるよ。

初心者さん

え、それだけなんですか?

エンジニアくん

実はそれが、ROMとRAMの使い方にも関わる重要な違いなんだ。


データ領域(.data)とは

データ領域とは、初期値を持つグローバル変数やstatic変数が配置される領域です。

int counter = 10;
static int flag = 1;

これらはデータ領域に配置されます。

ROM
 ├ 初期値 (.data)
 ↓ コピー
RAM
 ├ .data
 ├ .bss (0クリア)

重要ポイント

  • 実行時はRAMに存在する
  • しかし初期値はROMに保存されている
  • 起動時にROMからRAMへコピーされる

ここが非常に重要です。

マイコンは電源投入直後、RAMの内容は保証されません。
そのため、ROMに保存された初期値をスタートアップコードがRAMへコピーします。

つまりデータ領域は、

「RAMにあるが、初期値はROM由来」

という特徴を持ちます。

スタートアップコードについてはこちらで解説しています。


BSS領域(.bss)とは

BSS領域は、初期値を持たないグローバル変数やstatic変数が配置される領域です。

int buffer[1000];
static int status;

これらはBSS領域に配置されます。

BSSの特徴

  • 実行時はRAMに存在
  • ROMに初期値データを持たない
  • 起動時にゼロクリアされる

スタートアップコードは、

BSS領域を0で初期化

という処理を行います。


なぜデータ領域とBSS領域は分かれているのか?

ここが本質です。

理由① ROMを節約するため

BSS領域は「全部0」。

わざわざROMに0を保存する必要はありません。

もし分けなければ、

  • 1000要素の配列
  • すべて0

これをROMに格納することになります。

分離することで、実行ファイルサイズを削減できます。


理由② 起動処理を最適化するため

データ領域 → コピー処理
BSS領域 → memset(0)

処理を分けることで、初期化が効率化されます。


理由③ メモリ使用量を明確にするため

マップファイルを見ると、次のように表示されます。

.data   0x20000000   0x120
.bss    0x20000120   0x300

これにより、

  • ROM消費量(.data初期値分)
  • RAM消費量(.data + .bss)

を分けて把握できます。


実務で注意すべきポイント

① データ領域が増えるとROMが不足する

初期値を大量に持つと、
ROM使用量が一気に増えます。

② BSS領域が増えるとRAM不足になる

大きなバッファを定義すると、
RAMを圧迫します。

③ 「意図せずデータ領域に入る」ケース

int buffer[1000] = {0};

これはBSS領域ではなくデータ領域になります。

なぜなら「初期値あり」だからです。

この違いはRAM/ROM両方に効きます。

よくある誤解:= {0} は BSS 領域ではない

初期値が 0 の場合、BSS領域に入ると思われがちですが、
明示的に = {0} と書いた場合でも、
データ領域に配置される場合と、BSS領域に配置される場合があります。
これはコンパイラや最適化設定に依存します。

int buffer1[1000];

これは初期値なしのため BSS領域 に配置され、
起動時にゼロクリアされます。

int buffer2[1000] = {0};

こちらは初期値ありとみなされ、データ領域に配置される場合があります。
ROMに初期値が保存され、起動時にRAMへコピーされます。

記述配置領域ROM使用初期化方法
int buf[1000];BSS領域使わないゼロクリア
int buf[1000] = {0};データ領域の場合あり使うROMからコピー

ただし、これは 必ずしも避けるべきではありません。

例えば次のようなケースでは、明示的に書いた方が可読性が高くなります。

  • 初期値 0 であることを明確にしたい
  • コード規約で初期化を必須としている
  • 意図しない未初期化を防ぎたい

つまり、

可読性を優先 → = {0}
ROM削減を優先 → 初期値を書かない

という判断になります。

組み込み開発ではメモリ制約が厳しいため、
大きな配列では BSS領域を使う方が有利な場合が多いですが、
小さな変数では可読性を優先する設計も一般的です。

このように データ領域 とBSS領域の違いは、
単なる仕様ではなく 設計判断にも関わるポイント になります。


まとめ

項目データ領域BSS領域
初期値ありなし
RAM配置されるされる
ROM保存するしない
起動処理コピーゼロクリア
主な影響ROM消費RAM消費

データ領域とBSS領域を理解すると、

  • マップファイルが読める
  • メモリ不足の原因が追える
  • 組み込み開発の基礎が固まる

メモリ設計を意識する第一歩として、必ず押さえておきたいポイントです。

この記事が参考になった方へ

メモリ領域については他の記事でも解説しています。

メモリ領域解説シリーズの全体像はこちら

技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。

小さなご相談からでもお気軽にご連絡ください。

お問い合わせはこちら

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする


目次