8

組み込みソフトウェアでは、一般的な方法でスタックオーバーフローをどのように処理しますか?最近のAMDプロセッサのようにハードウェアで保護するプロセッサに出くわしました。ウィキペディアにはいくつかのテクニックがありますが、それらは実際の実用的なアプローチですか?

今日の32ビット組み込みプロセッサですべての場合に機能する明確な提案されたアプローチを誰かが与えることができますか?

4

4 に答える 4

13

理想的には、スタックを静的に使用してコードを記述します (再帰呼び出しはありません)。次に、次の方法で最大スタック使用量を評価できます。

  1. 静的解析 (ツールを使用)
  2. 完全なコード カバレッジでコードを実行している間のスタック使用量の測定 (または、めったに実行されないコードが特に多くを使用しない限り、スタック使用量の範囲を確立したという合理的な自信が得られるまで、可能な限り高いコード カバレッジ)通常の実行パスよりもスタック)

しかし、それでも、可能であれば、より堅牢にするために、スタックオーバーフローを検出して処理する手段が必要です。これは、プロジェクトの開発段階で特に役立ちます。オーバーフローを検出するいくつかの方法:

  1. プロセッサがメモリ読み取り/書き込み割り込み (メモリ アクセス ブレークポイント割り込み) をサポートしている場合、スタック領域の最も遠い範囲を指すように構成できます。
  2. メモリ マップ構成で、「スタック ガード」領域である小さい (または大きい) RAM ブロックを設定します。既知の値を入力します。組み込みソフトウェアでは、定期的に (合理的に可能な限り頻繁に) この領域の内容を確認してください。変更された場合は、スタック オーバーフローを想定してください。

それを検出したら、それを処理する必要があります。コードがスタック オーバーフローから正常に回復できる方法はあまり知りません。スタック オーバーフローが発生すると、プログラム ロジックはほぼ確実に無効になるからです。だからあなたができることは

  1. エラーを記録する
    1. エラーをログに記録すると、症状 (予期しない再起動) の診断が非常に難しくなるため、非常に役立ちます。
    2. 警告: ログ ルーチンは、スタックが破損したシナリオでも確実に実行できる必要があります。ルーチンは単純であるべきです。つまり、スタックが破損していると、おそらく、派手な EEPROM 書き込みバックグラウンド タスクを使用して EEPROM に書き込もうとすることはできません。おそらく、この目的のために予約されている非初期化 RAM の構造体にエラーを記録し、再起動後に確認できます。
  2. 再起動します (または、特にエラーが繰り返し発生する場合はシャットダウンします)。
    1. 考えられる代替手段: RTOS を使用していて、システムがスタックの破損が分離されるように設計されており、他のすべてのタスクがそのタスクの再起動を処理できる場合は、特定のタスクだけを再起動します。これには、いくつかの深刻な設計上の考慮事項が必要です。
于 2009-07-27T02:40:35.950 に答える
2

埋め込みスタック オーバーフローは、再帰関数が手に負えなくなることによって引き起こされる可能性がありますが、ポインタの使用方法の誤り (これは別の種類のエラーと見なされる可能性があります) や、スタック サイズが小さい場合の通常のシステム操作によっても発生する可能性があります。つまり、スタックの使用状況をプロファイリングしないと、欠陥やバグの状況以外で発生する可能性があります。

スタックオーバーフローを「処理」する前に、それを特定する必要があります。これを行うための適切な方法は、初期化中にスタックにパターンをロードし、実行時にどの程度のパターンが消えるかを監視することです。このようにして、スタックが到達した最高点を特定できます。

パターン チェック アルゴリズムは、スタックの成長と逆方向に実行する必要があります。したがって、スタックが 0x1000 から 0x2000 に増加した場合、パターン チェックを 0x2000 から開始して効率を高めることができます。パターンが 0xAA で、0x2000 の値に 0xAA 以外の値が含まれている場合、オーバーフローが発生している可能性があります。

また、オーバーフローを検出した場合にデータを失うことなくシステムをシャットダウンできるように、スタックの直後に空の RAM バッファーを配置することも検討する必要があります。スタックの直後にヒープまたは SRAM データが続く場合、オーバーフローを特定することは、既に破損していることを意味します。あなたの緩衝材はあなたをもう少し長く保護します。32 ビットのマイクロでは、少なくとも小さなバッファーを提供するのに十分な RAM が必要です。

于 2009-07-27T01:52:08.370 に答える
2

メモリ管理ユニットを備えたプロセッサを使用している場合、ハードウェアは最小限のソフトウェア オーバーヘッドでこれを行うことができます。最近のほとんどの 32 ビット プロセッサにはこれらが搭載されており、ますます多くの 32 ビット マイクロ コントローラにも搭載されています。

スタックに使用するメモリ領域を MMU に設定します。MMU がアクセスを許可しない 2 つのメモリ領域に隣接する必要があります。アプリケーションの実行中に、スタックがオーバーフローするとすぐに例外/割り込みが発生します。

エラーが発生した瞬間に例外が発生するため、アプリケーションのどこでスタックが悪くなったかを正確に知ることができます。コール スタックを見て、現在の場所に到達した方法を正確に確認できます。これにより、問題が発生してからずっと後に問題を検出して何が問題なのかを突き止めようとするよりも、問題を見つけるのがはるかに簡単になります。

私はこれを PPC および AVR32 プロセッサでうまく使用しました。MMU を使い始めたときは、何年も MMU なしでうまくやっていたので、時間の無駄だと感じますが、メモリの問題が発生した正確な場所で例外の利点を確認すると、二度と戻ることはありません。RAM の下部パークへのメモリ アクセスを許可しない場合、MMU はゼロ ポインタ アクセスを検出することもできます。

RTOS を使用している場合、MMU はメモリを保護し、1 つのタスクのエラーが他のタスクのスタックに影響を与えることはありません。これは、他のタスクに影響を与えることなく、タスクを簡単に再開できることを意味します。

これに加えて、通常、MMU を備えたプロセッサには大量の RAM が搭載されているため、プログラムがスタックをオーバーフローする可能性ははるかに低く、小さなメモリ フット プリントでアプリケーションを正しく実行するためにすべてを微調整する必要はありません。

これに代わる方法は、プロセッサのデバッグ機能を使用して、スタックの最後へのメモリ アクセスで割り込みを発生させることです。これはおそらく非常にプロセッサ固有です。

于 2009-07-27T06:24:34.980 に答える
1

スタック オーバーフローが発生しました コール スタックが大きすぎてスタック メモリが使い果たされましたか? たとえば、再帰関数のレベルが深すぎます。

スタックの後に既知のデータを配置することでスタック オーバーフローを検出する手法があり、スタックが大きくなりすぎて上書きされた場合に検出できます。

GnatStack、AbsInt の StackAnalyzer、Bound-T などの静的ソース コード分析ツールがあり、実行時の最大スタック サイズを決定または推測するために使用できます。

于 2009-07-27T01:33:49.663 に答える