組込み開発とメモリ管理の苦労話
私はそろそろ情報処理業界やソフトウェア開発業界から引退を考えている年寄エンジニアです。エンジニアはどうあるべきか、など日頃考えている事、感じた事をとめどなく書いてみようと思います。
このコラムを読まれた方の中には、違う意見や考えをお持ちの方もおられると思います。その時は無視して頂ければ幸いです。
複数チーム進めたある組込み開発プロジェクト
あるネットワーク装置の組込み開発していた時の話です。複数のチームに分かれて開発を行っていました。
私が所属するチームは、FPGA(Field-Programmable Gate Array)とそのFPGAを制御するドライバの組込み開発が担当でした。別のチームは、より上位のアプリケーションの開発を行っていました。
基本的なチェックを終えて、システムテスト中にシステムがクラッシュするという不具合に遭遇しました。初期の解析で、アプリケーションに起因する不具合であることを突き止めました。アプリケーションの不具合である以上、より詳細な不具合解析と対処はアプリケーションを担当する別チームの仕事です。
別チームの不具合を待つ
我々のチームは、既にチェックを完了していますので、別チームの不具合対処を待つことしかできません。しかし、待てど暮らせど不具合が解消する気配がないのです。このままでは埒が明きません。
いい加減しびれを切らして別チームに状況を聞くと、逆に不具合解析のサポート依頼をされてしまいました。本来は我々の仕事ではありませんが、テストが終わらないと撤収できなので仕方なく手伝うことにしました。
不具合の発生条件と対策
発生条件を聞くと、特定のトランザクションが入力時に発生することが分かりました。実装担当に特定トランザクション入力時の処理と実装の説明を受けている時に、ふとソースを見るとローカル変数に巨大な配列を定義していることに気が付きました。
状況とソース等を確認し、障害の原因として以下ではないか、と想定しました。
- 障害を引き起こす特定のトランザクションの処理は複雑で、障害を引き起こす関数までのコールが深い
- スタックを消費して残り少ない状況に、巨大なローカル変数でスタックを食いつぶしてスタックオーバーフローを発生し、メモリ破壊を発生させた
実装担当には、ローカル変数の使い方等の再確認と対処をお願いしました。対処後は不具合は発生しなくなりました。とりあえず解決したようです。
組込み開発で重要なメモリ管理
実装担当に、なぜ巨大な配列をローカル変数に定義したのか、スタックサイズやローカル変数のメモリ配置について理解はあるか、などを聞きましたが、残念ながら彼は基本的な知識を不足していることが分かりました。彼は汎用コンピューターで動くアプリケーションしか開発した経験がなかったようです。(汎用コンピューターは一般に数MB以上のスタックサイズを確保しています。組込みシステムでは数KBしか確保しないことが多いです。)
組込み開発ではスタック機構を理解がより重要
組込みシステムでは、スタックの機構についての知識や、スタックサイズに留意することが必要です。スタックについては、ホームページでの解説(例えば スタックと割り込み ―― プログラムが動く仕組みを知ろう など)が豊富にありますので、是非勉強して理解して欲しいと思います。
コンパイラーや開発ツールによっては、関数コールのクリティカルパスでのスタック消費量をレポートするものもあります。また、デバッガが動的に監視して、スタックオーバーフロー発生時に例外を発生させる機能もあります。ただ、組込みシステムでの貧弱なツールや環境では、知らず知らずのうちにスタックオーバーフローを起こして、今回のように動かしてみて初めて気付く、という場合も多くあります。
スタック機構を理解していると、ローカル変数、関数コールの引数や戻り値を使いこなす一助になりますので、改めてですが是非勉強してください。
ちなみに、当社では組込み開発を始め、様々なシステム開発の相談、設計、実装を全国対応で行なっています。無料相談も実施していますので、お気軽にご相談ください。