GAIO CLUB

2023年08月28日

【第11回】ヒープエリア

静的解析/コンパイラ技術
いまさら聞けない 静的解析/コンパイラ技術
組み込みソフトではあまり使用しないかもしれませんが、ヒープエリアと呼ばれる領域があります。
malloc(calloc・reallocを含む)を使用した時に使われるエリアです。スタックフレームと同じようにRAMエリアを使用します。

mallocはCコンパイラが提供するライブラリですが、組み込みの場合、使用できるRAMエリアの場所(アドレス)を知りません。ですから、mallocに伝える何らかの方法を用意していて、その設定を使用者に求めます。GAIO製Cコンパイラのmallocでは_sbrkを呼び出してユーザから使用可能なメモリを取得していましたが、この方法をとるCコンパイラも珍しくありません。

malloc管理情報

mallocで確保したエリアをfreeすると、再びmallocが使用します。
そのために、mallocとfreeは使用中のメモリと空きメモリを示す管理情報を作り、これをチェーンして管理することが多いと思います。
malloc管理情報
しかし、図を見てお分かりの通り、mallocで確保したエリアの前後には管理情報があり、もし、確保したサイズ以上のエリアを使ってしまったら、管理情報を破壊してしまうことになります(赤矢印)。

mallocとfreeは管理情報を信じて動くので、もし管理情報を破壊してしまうと、次々にメモリを破壊し、プログラム動作中に突然どこかのエリアが壊れるような問題が発生します。
領域外を壊すのはいつでも大問題ですが、malloc管理情報を壊したときのデバッグはとても苦労します。

フラグメンテーション

アロック要求に対して、どの空きエリアを渡すのかは、mallocの作りに依存します。速度を優先したアロック方法や、無駄な空きエリアをできる限り増やさない方法など、いくつかの方法があります。

要求サイズぴったりの空きエリアがあれば良いのですが、無い時は大きな空きエリアの一部を切り出して使用することになり、これを続けていると、小さな空きエリアが増えてゆきます。
ファイルをまとめて保存できなくなった状態を断片化 (フラグメンテーション)と呼びますが、空きエリアがこのような状態になると、mallocが管理している全体の大きさに対する使用可能エリアの割合が小さくなります。

そのため、mallocのためにどれくらいのRAMエリアを用意しておけば良いのかの判断はとても難しいです。

スタックかヒープか

メモリ設計上、スタックとヒープを合わせたエリアを用意することは多いと思います。
たとえば、大きなRAMエリアを用意しておき、上からヒープ、下からスタックを使う方法です。

ヒープとスタックがぶつかってしまうとどちらかが壊れてしまうので、余裕のある大きさが必要です。


ヒープ使用量の見積もりはスタック見積もりより難しいので、必要なサイズが決まっているのであればヒープを使わず、スタックだけで動くことも可能かもしれません。たとえばオート変数の配列を使用した場合、オート変数は関数終了後に親関数へ戻ると解放されるので、free忘れの心配もありません。

しかし、オート変数は関数が動いている間だけ使えるエリアですから、子関数に使わせることはできても、親関数など、自分がリターンした後で動作する関数に使わせることはできません。
コーディングガイドラインにも、“オート変数のアドレスを関数終了後に使用可能な状態にしてはならない”というルールがある通りです。

筆者紹介

浅野 昌尚(あさの まさなお)

ガイオ・テクノロジー株式会社

開発1部 QTXグループ

1980年代から30年以上にわたり汎用構造のCコンパイラ開発に従事し、その間に8ビットマイコンからRISC・VLIW・画像処理プロセッサまで、さまざまなCPU向けのクロスCコンパイラを開発。

人気のコラム

最新のコラム