6

Bjarne Stroustrup によるThe Design and Evolution of C++ を読んでいます。例外処理と非同期シグナルに関しては、以下のように言及されています。

シグナルなどを処理するために例外を使用できますか? ほとんどの C 環境ではそうではありません。問題は、C が再入可能ではない malloc のような関数を使用することです。malloc の途中で割り込みが発生して例外が発生した場合、例外ハンドラが malloc を再度実行するのを防ぐ方法はありません。

呼び出しシーケンスとランタイム ライブラリ全体が再入可能性の要件に合わせて設計されている C++ 実装では、シグナルが例外をスローできるようになります。

「例外ハンドラが malloc を再度実行するのを防ぐ方法はない」という文の著者の意味は何ですか? 関数を再入可能にすると、どのようにしてシグナル ハンドラから例外をスローできるようになりますか?

4

3 に答える 3

6

私の意見では、その部分は現在の C++ ではあまり意味がありません。

C++ では、例外をシグナルとして使用する方法はありません。これは、シグナルがハンドラーを実行し、その後 (おそらく) 実行を継続することを意図しているためです。

ただし、C++ の例外はこの方法では機能しません。例外ハンドラーに到達すると、スタックはすでにロールバックされており、処理後に「続行」する方法はありません。スローに続くステートメントに到達する方法はありません (または、例外が発生する関数呼び出しに続くステートメントに到達する方法はありません)。投げた)。

シグナルは非同期ですが、中断することはなく、シグナルが可能になった後も継続します (もちろん、シグナル ハンドラーで何が行われるかについて注意を払う必要があります)。

この 2 つのアイデアは論理的なレベルでは互換性がなく、ライブラリが再入可能かどうかは問題ではないと思います。

初期のC++設計には、例外の再開オプションがあった可能性があります...

于 2011-06-30T14:41:29.573 に答える
3

たとえば、malloc の呼び出しによってシグナルが生成された場合、そのシグナル ハンドラから例外をスローすると、例外スロー ロジックによって malloc が再度呼び出される可能性があります。malloc は再入可能ではないため、未定義の動作が発生します。

シグナルを処理する 1 つの方法は、シグナル イベントをイベント キューにプッシュし、シグナル ハンドラからすぐに戻ることです。次に、イベントループがシグナルイベントを処理するときに、シグナルハンドラの制限されたコンテキストにないため、必要なことは何でも実行できます。

于 2011-06-30T14:04:23.790 に答える
1

関数が実行中に中断され、中断された呼び出しが完了する前に再度呼び出される場合、その関数は「再入可能」です。別の見方をすると、再入可能関数はシグナル ハンドラ内から呼び出すことができます。シグナル ハンドラー内から再入不可関数を呼び出す場合、すべての賭けは無効になります。シグナル ハンドラー内から呼び出す必要がある関数は、再入可能であることがわかっている関数だけです。

malloc は再入可能ではありません。malloc がカブームになった場合、割り当てられたデータを追跡するために malloc がバックグラウンドで使用するグローバル データを更新している最中にカブームになったかどうかを判断する方法はありません。

シグナル ハンドラーと例外の別の問題: シグナル ハンドラーで実行されるコードは、基本的にメイン コードとは異なるスレッドで実行されます。シグナルをアドレス指定できる場合、シグナル ハンドラからのリターンは、シグナルが発生したポイントの直後に戻ります。シグナル ハンドラーでどのように例外をスローしますか? これを行うと、シグナル ハンドラが返されなくなります。つまり、残りの実行はシグナル ハンドラ内から効果的に行われます。別の信号が発生するとどうなるでしょうか。2 つの概念が混ざり合うことはありません。再入可能性は、ここでは氷山の一角にすぎません。

于 2011-06-30T14:18:44.400 に答える