運営や開発の現場で幾度となく経験してきた「開発環境では普通に動くのに、実機では固まる」「ビルドは通っているのに、実機では起動しない」という不具合はかなり困ります。
コードだけを見ていると問題なさそうに見える。デバッグ環境では再現しない。ログを入れると出なくなる。
こういう症状は、原因が見つかるまで時間がかかります。
組み込み系エンジニアの間でこの話題が出ていましたが、これは組み込み系やアーケードゲームに限った話ではありません。モバイル機でも、ガラケーでも、近い状況は何度も見てきました。
開発環境では動く、だけでは何の保証もない
開発環境で動いていると、どうしても「コード・設計は間違っていない」と思いたくなります。
もちろん、その見方が完全に間違いというわけではありません。開発環境で動いているなら、処理の流れや大まかな実装方針は成立している可能性があります。
ただ、組み込み系や実機に近い開発では、「開発環境で動いた」という事実だけでは足りないことがあります。
実機では、メモリの状態、初期化の順番、割り込みのタイミング、デバイスのReady待ち、DMAの転送範囲などが、かなり素直に症状として出ます。
開発環境では見えていなかった不安定さが、実機ではそのまま固まりや起動失敗になります。
ここで見るべきなのは、人のミスというより、開発環境と実機の条件差です。
最短で疑うべき4つのポイント
「実機で固まる」「実機で起動しない」とき、最初に見るポイントはある程度決まっています。
1.未初期化と初期化順序
スタック、レジスタ、作業領域が、想定した状態になっているかを確認します。開発環境ではたまたまゼロに見えていた領域が、実機では前回の値や不定値を持っていることがあります。
2.割り込みの許可タイミング
初期化が終わる前に割り込みが飛んでいないか。割り込みハンドラ側が参照する領域は、すでに使える状態になっているか。ここがずれると、起動直後だけ固まる、まれに起動しない、といった症状になりやすいです。
3.ポーリング待ち不足
Readyを見ているか、最低ウェイトが足りているかを確認します。実機ではデバイスの応答が開発環境より素直に遅れることがあります。待つべきところで待てていないと、次の処理が早く進みすぎます。
4.メモリ破壊
スタックの深さ、配列の範囲、DMAのはみ出しを見ます。特にDMAは、転送元や転送先、サイズ指定のずれがあると、関係なさそうな領域まで壊します。症状だけ見ると別の処理が悪く見えるので、原因の切り分けに時間がかかります。
なぜ開発環境では動くのかを確認する
実機で止まると、どうしても「なぜ実機だけ止まるのか」を追いたくなります。ただ、別視点から確認したいのが「なぜ開発環境では動いているのか」です。
・ICEがメモリを初期化している。
・割り込みタイミングが実機より遅い。
・デバッグ中に自然なウェイトが入っている。
こうした条件がそろっていると、本来は不安定なコードでも開発環境では動いて見えることがあります。
ログを追加したら再現しなくなる、ステップ実行だと落ちない、ICE接続時だけ動く。こういうときは、ログやデバッグ操作によって処理順やタイミングが変わっていないかを見たほうがよいです。
問題なく動いているのではなく、壊れない条件がそろっていただけ、という状態はあります。
たまたま動いている状態を切り分ける
実機トラブルで難しいのは、症状が毎回きれいに出るとは限らない点です。
起動直後だけ止まる。
何回かに一回だけ固まる。
ビルド設定を変えると出る。
ログを入れると出なくなる。
デバッグビルドでは動くのに、リリースビルドでは止まる。
このあたりの症状は、初期化漏れ、タイミング差、メモリ破壊と相性がよいです。相性がよいという言い方は少し変ですが、調査するときの疑い先としてはかなり自然です。
この場合、コードの見た目だけでは判断しにくくなります。
最後に再現した条件と、再現しなくなった条件を分けて記録し、差分を追える形にしたほうが調査しやすくなります。
ビルド設定、最適化、ログの有無、ICE接続の有無、割り込み許可の位置、デバイス初期化の順番。
こうした条件を分けて見ると、実装担当者が次に確認する範囲を絞りやすくなります。
実機トラブルで見る確認ポイント
実機で固まる、起動しない、開発環境では再現しない。
この状態では、原因をひとつに決めつけるより、条件差を減らしながら確認したほうが進めやすいです。
確認するなら、次のような順番が現実的です。
・最後に再現したビルドと、再現しなくなったビルドの差分を見る
・未初期化の変数、作業領域、スタック、レジスタの状態を確認する
・初期化が終わる前に割り込みが許可されていないかを見る
・割り込みハンドラが参照する領域の初期化順序を確認する
・Ready待ち、最低ウェイト、ポーリング条件を見直す
・スタック深さ、配列範囲、DMA転送範囲を確認する
・ログ追加やステップ実行で処理順やタイミングが変わっていないかを見る
・ICE接続時と実機単体で、メモリ初期値や割り込みタイミングが変わっていないか確認する
開発環境で動くことは、安心材料にはなります。
ただ、それだけで実機でも安定しているとは限りません。
実機でだけ出る不具合は、コードの正しさだけでなく、動いている条件そのものを見る必要があります。
どの環境で、どの順番で、どのタイミングで、どのメモリを触っているのか。
そこを分けて確認できると、「たまたま動いていた状態」と「本当に安定して動いている状態」を切り分けやすくなります。
おわりに
X(旧Twitter)やBlueskyを中心に日々発信しております。
是非他のSNSもご覧いただけますと幸甚でございます。
https://x.com/itchie_tatsumi
https://bsky.app/profile/itchie-tatsumi.bsky.social
https://www.facebook.com/ichino.souta
また、辰巳電子工業SS事業部では、エンジニアが安心して長く働ける環境づくりに取り組んでおります。「今の経験で応募できるか知りたい」「案件やキャリア支援について聞いてみたい」という方は、是非カジュアル面談からお気軽にご相談願います。