3

コンパイラ フラグとシグナル処理を使用して整数オーバーフローを処理できることを理解しています (この質問に対する受け入れられた回答を参照してください)。
実際、それを防ぐことはできます。

ただし、スタックオーバーフローを処理/回避する方法に関する情報を見つけることができませんでした:

void breakStack(int num){
     // Implied check to see if addition will cause integer overflow
     int tmp = num + 1;
     // Code to see if next call will cause a stack
     // overflow and avoid it
     breakStack(tmp);
}

または:

void breakStack(int num){
    // Implied check to see if addition will cause integer overflow
    int tmp = num + 1;
    breakStack(tmp);
}

void stackOverFlowHandler(int signum){
    // Code to handle stack overflow
}

私が見つけた2つの解決策は、「再帰を使用しないでください」と「コンパイラの最適化により末尾の再帰を削除できるため、問題は解決しました」です。しかし、私は別の解決策を探しています。

編集:私はそれを避ける方法が好きです(受け入れられた答えを見てください)。

回避策:
関数のサイズ (例: 50 バイト)、およびスタックに残っている空き容量 (例: 200 バイト) があるとします。

void tryToBreakStack(int num){
    // Implied check to see if addition will cause integer overflow
    int tmp = num + 1;
    if(functionSize>leftSpace){
        return;
    }
    tryToBreakStack(tmp);
}

これで、 nm -S を使用して関数のサイズを取得し、それをハードコーディングできるかもしれません(受け入れられた答えでは、それはできないと言っています)。追記: sizeof(tryToBreak) または sizeof(&tryToBreak) を呼び出しても、この値を取得できないことはほぼ確実です。
さらに、スタック サイズを設定して、スタック上の空き領域の大まかな概算を取得できる場合があります。

その解決策に取り組み始める前に (そしておそらく失敗するのを見る前に)、別の方法があるかどうかを知りたいです (おそらく、より簡単で正確な方法です)。

編集:それを回避する方法を見つけたので、本当の問題は、シグナル処理を使用してスタックオーバーフローからどのように回復するかです。

対処法:プロセスが「セグメンテーション違反」シグナルを受信し、それを処理
する必要がある場合、どうすればよいかわかりません。1 つ目: スタック オーバーフローが原因であることがどのようにわかりますか? 2 つ目: スタック オーバーフローから何を回復しますか?

4

1 に答える 1

2

独自のスタックを定義することは可能ですが、完全に移植可能な方法で行うのは困難です。原則として、posix スレッド (「参考文献」を参照pthread_set_stackaddr) を使用して実行できるため、特に風変わりなものではありません。

次にmprotect、スタックの最後にレッド ゾーン (「ガード エリア」) を作成するために使用できます。スタック オーバーフローにより、SIGSEGV処理可能な が発生します。sigaction ハンドラーには保護違反のアドレスが提供されるため、ハンドラーをチェックインして、レッドゾーンの一部であるかどうかを確認できます。(もちろん、別のスタックでシグナル ハンドラを実行する必要があります。SA_ONSTACKフラグとsigaltstack.

スタック オーバーフローからの回復 (コンパイラの支援なし) は、よりトリッキーです。

ところで、関数 (一連の機械語命令からなる再配置可能なオブジェクト) のサイズと関数のスタック フレームのサイズの間には関係がありません。だからnm本当にあなたに何の役にも立ちません。

于 2013-10-20T18:58:32.137 に答える