組み込みソフトウェアでは、一般的な方法でスタックオーバーフローをどのように処理しますか?最近のAMDプロセッサのようにハードウェアで保護するプロセッサに出くわしました。ウィキペディアにはいくつかのテクニックがありますが、それらは実際の実用的なアプローチですか?
今日の32ビット組み込みプロセッサですべての場合に機能する明確な提案されたアプローチを誰かが与えることができますか?
組み込みソフトウェアでは、一般的な方法でスタックオーバーフローをどのように処理しますか?最近のAMDプロセッサのようにハードウェアで保護するプロセッサに出くわしました。ウィキペディアにはいくつかのテクニックがありますが、それらは実際の実用的なアプローチですか?
今日の32ビット組み込みプロセッサですべての場合に機能する明確な提案されたアプローチを誰かが与えることができますか?
理想的には、スタックを静的に使用してコードを記述します (再帰呼び出しはありません)。次に、次の方法で最大スタック使用量を評価できます。
しかし、それでも、可能であれば、より堅牢にするために、スタックオーバーフローを検出して処理する手段が必要です。これは、プロジェクトの開発段階で特に役立ちます。オーバーフローを検出するいくつかの方法:
それを検出したら、それを処理する必要があります。コードがスタック オーバーフローから正常に回復できる方法はあまり知りません。スタック オーバーフローが発生すると、プログラム ロジックはほぼ確実に無効になるからです。だからあなたができることは
埋め込みスタック オーバーフローは、再帰関数が手に負えなくなることによって引き起こされる可能性がありますが、ポインタの使用方法の誤り (これは別の種類のエラーと見なされる可能性があります) や、スタック サイズが小さい場合の通常のシステム操作によっても発生する可能性があります。つまり、スタックの使用状況をプロファイリングしないと、欠陥やバグの状況以外で発生する可能性があります。
スタックオーバーフローを「処理」する前に、それを特定する必要があります。これを行うための適切な方法は、初期化中にスタックにパターンをロードし、実行時にどの程度のパターンが消えるかを監視することです。このようにして、スタックが到達した最高点を特定できます。
パターン チェック アルゴリズムは、スタックの成長と逆方向に実行する必要があります。したがって、スタックが 0x1000 から 0x2000 に増加した場合、パターン チェックを 0x2000 から開始して効率を高めることができます。パターンが 0xAA で、0x2000 の値に 0xAA 以外の値が含まれている場合、オーバーフローが発生している可能性があります。
また、オーバーフローを検出した場合にデータを失うことなくシステムをシャットダウンできるように、スタックの直後に空の RAM バッファーを配置することも検討する必要があります。スタックの直後にヒープまたは SRAM データが続く場合、オーバーフローを特定することは、既に破損していることを意味します。あなたの緩衝材はあなたをもう少し長く保護します。32 ビットのマイクロでは、少なくとも小さなバッファーを提供するのに十分な RAM が必要です。
メモリ管理ユニットを備えたプロセッサを使用している場合、ハードウェアは最小限のソフトウェア オーバーヘッドでこれを行うことができます。最近のほとんどの 32 ビット プロセッサにはこれらが搭載されており、ますます多くの 32 ビット マイクロ コントローラにも搭載されています。
スタックに使用するメモリ領域を MMU に設定します。MMU がアクセスを許可しない 2 つのメモリ領域に隣接する必要があります。アプリケーションの実行中に、スタックがオーバーフローするとすぐに例外/割り込みが発生します。
エラーが発生した瞬間に例外が発生するため、アプリケーションのどこでスタックが悪くなったかを正確に知ることができます。コール スタックを見て、現在の場所に到達した方法を正確に確認できます。これにより、問題が発生してからずっと後に問題を検出して何が問題なのかを突き止めようとするよりも、問題を見つけるのがはるかに簡単になります。
私はこれを PPC および AVR32 プロセッサでうまく使用しました。MMU を使い始めたときは、何年も MMU なしでうまくやっていたので、時間の無駄だと感じますが、メモリの問題が発生した正確な場所で例外の利点を確認すると、二度と戻ることはありません。RAM の下部パークへのメモリ アクセスを許可しない場合、MMU はゼロ ポインタ アクセスを検出することもできます。
RTOS を使用している場合、MMU はメモリを保護し、1 つのタスクのエラーが他のタスクのスタックに影響を与えることはありません。これは、他のタスクに影響を与えることなく、タスクを簡単に再開できることを意味します。
これに加えて、通常、MMU を備えたプロセッサには大量の RAM が搭載されているため、プログラムがスタックをオーバーフローする可能性ははるかに低く、小さなメモリ フット プリントでアプリケーションを正しく実行するためにすべてを微調整する必要はありません。
これに代わる方法は、プロセッサのデバッグ機能を使用して、スタックの最後へのメモリ アクセスで割り込みを発生させることです。これはおそらく非常にプロセッサ固有です。
スタック オーバーフローが発生しました コール スタックが大きすぎてスタック メモリが使い果たされましたか? たとえば、再帰関数のレベルが深すぎます。
スタックの後に既知のデータを配置することでスタック オーバーフローを検出する手法があり、スタックが大きくなりすぎて上書きされた場合に検出できます。
GnatStack、AbsInt の StackAnalyzer、Bound-T などの静的ソース コード分析ツールがあり、実行時の最大スタック サイズを決定または推測するために使用できます。