C言語のメモリ領域を徹底解説|text・data・bss・heap・stackの違いとは?

目次

メモリ領域解説シリーズ

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

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

組み込み開発やC言語を扱うエンジニアにとって、「メモリ構造の理解」は避けて通れません。

なんとなく

  • グローバル変数はdata?
  • 初期化なしはbss?
  • mallocはheap?

と覚えているだけでは、本質的な理解とは言えません。

この記事では、Cプログラムのメモリ領域について体系的に整理します。


プロセスのメモリ全体像

一般的なプロセスのメモリ構造は次のようになります。

上から順番に解説します。


テキスト領域(コード領域)

ここには実行される命令そのものが入ります。

  • 関数の中身
  • 実行命令
  • constな定数(※環境による)

組み込みでは、ほとんどの場合**フラッシュメモリ(Flash)**に配置されます。

つまり:

  • 実行はできる
  • 書き換えはできない(通常)

という特徴があります。

なぜ重要か?

テキスト領域が増えるということは、
プログラムサイズが増えるということです。

フラッシュ容量が小さいマイコンでは、これも制約になります。


データ領域(初期化済みグローバル変数)

ここには、

  • 初期値が与えられているグローバル変数
  • static変数(初期値あり)

が入ります。

例:

int count = 10;
static int mode = 1;

重要なのはここ。

👉 初期値も含めてRAMに展開される

組み込みでは:

  • フラッシュに初期値を保持
  • 起動時にRAMへコピー

という動きをします。

つまり、データ領域が大きいと:

  • 起動時間が伸びる
  • RAMを消費する

という影響があります。


BSS領域(未初期化グローバル変数)

ここは初心者が一番あいまいな部分です。

例:

int buffer[1000];

初期値を書いていないグローバル変数は、
ビーエスエス(BSS)領域に入ります。

BSSの特徴

  • 実行開始時にゼロクリアされる
  • 実行ファイルに実データを持たない
  • RAMのみ消費する

なぜゼロになるのか?

C言語仕様で「静的記憶域の変数はゼロ初期化」と決まっているからです。

組み込みでの怖さ

巨大配列をここに置くと、

👉 一瞬でRAMが足りなくなる

マップファイルを見たらBSSがほぼRAMを埋めていた、
というのはあるあるです。


ヒープ領域(動的確保エリア)

mallocで確保するのがヒープです。

特徴:

  • 実行中にサイズが変わる
  • freeしないと解放されない
  • フラグメンテーション(断片化)が起こる

組み込みで嫌われる理由はここ。

  • 予測不能
  • 断片化する
  • メモリリークが致命傷

リアルタイム性が重要な環境では、
ヒープを使わない設計も多いです。

組み込み開発でmallocが嫌われる理由については、こちらの記事でも解説しています。


スタック領域(関数呼び出しエリア)

関数が呼ばれるたびに使われるのがスタック。

ここに置かれるのは:

  • ローカル変数
  • 引数
  • 戻りアドレス

スタックは上から下へ伸びるのが一般的です。

危険ポイント

  • 再帰
  • 巨大ローカル配列
  • 深い関数ネスト

これらはスタックオーバーフローを引き起こします。

組み込みでは、
スタックサイズをリンカ設定で固定します。

つまり:

👉 設計ミス=即ハング

です。


RAMとFlashの整理

組み込みでは、

  • テキスト → Flash
  • データ → RAM
  • ビーエスエス → RAM
  • スタック → RAM
  • ヒープ → RAM

つまり本当に怖いのはRAM不足です。

マイコンはFlashよりRAMの方が圧倒的に小さい。

だからメモリ設計が重要になります。

マップファイルの見方

ビルドすると生成される .map ファイル。

例えばこんな記述があります:

Memory ConfigurationName            Origin             Length
FLASH                               0x08000000         512K
RAM                                 0x20000000         128K

そして下の方に:

.bss      0x20000000      0x00004000
.data     0x20004000      0x00001000

ここで見るべきは:

  • BSSサイズ
  • dataサイズ
  • 合計RAM使用量
  • stack確保サイズ

さらには、

  • 最大スタック使用量
  • RAMの残り容量

を確認することが、安全設計に直結します。

メモリマップについてはこちらの記事で解説しています。


実際にRAMが足りなくなるとどうなるか

RAM不足は、必ずしもビルドエラーにはなりません。

  • 起動時にハングする
  • 特定条件でのみ不安定になる
  • まれに再現する不具合が発生する

こうした症状は、メモリ破壊やスタックオーバーフローが原因であることが多いです。

そのため、設計段階で

  • どの領域がRAMを消費しているか
  • 最大使用量はいくつか
  • 安全マージンは確保されているか

を確認することが不可欠になります。




なぜこの理解が設計力につながるのか

前回の記事で触れた通り、

「どこに何が置かれるか」を知らずに設計すると、

  • なんとなくグローバル変数を増やす
  • なんとなくmallocを使う
  • スタックサイズを考えない

というコードになります。

でも、メモリ領域を理解していると、

  • この配列はスタックに置くと危険
  • これはBSSでRAMを圧迫する
  • 初期化コストが起動時間に影響する

と判断できる。

これが設計力です。


まとめ

メモリ領域は「試験対策の暗記項目」ではありません。

  • テキスト
  • データ
  • ビーエスエス
  • ヒープ
  • スタック

それぞれの役割と制約を理解することが、

組み込みエンジニアとしての土台になります。

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

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

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

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

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

お問い合わせはこちら

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

この記事を書いた人

コメント

コメントする


目次