C ++の例外処理メカニズムがどのように機能するかに興味があります。具体的には、例外オブジェクトはどこに保存され、キャッチされるまで複数のスコープをどのように伝播しますか?グローバルエリアに保管されていますか?
これはコンパイラ固有である可能性があるため、誰かがg ++コンパイラスイートのコンテキストでこれを説明できますか?
C ++の例外処理メカニズムがどのように機能するかに興味があります。具体的には、例外オブジェクトはどこに保存され、キャッチされるまで複数のスコープをどのように伝播しますか?グローバルエリアに保管されていますか?
これはコンパイラ固有である可能性があるため、誰かがg ++コンパイラスイートのコンテキストでこれを説明できますか?
回答:
実装は異なる場合がありますが、要件に続くいくつかの基本的な考え方があります。
例外オブジェクト自体は、1つの関数で作成され、その呼び出し元で破棄されたオブジェクトです。したがって、通常、スタック上にオブジェクトを作成することは不可能です。一方、多くの例外オブジェクトはそれほど大きくありません。エルゴ、たとえば32バイトのバッファを作成し、より大きな例外オブジェクトが実際に必要な場合は、オーバーフローしてヒープにすることができます。
実際の支配権の移転に関しては、2つの戦略が存在します。1つは、スタックを巻き戻すのに十分な情報をスタック自体に記録することです。これは基本的に、実行するデストラクタと、例外をキャッチする可能性のある例外ハンドラのリストです。例外が発生した場合は、一致するキャッチが見つかるまで、これらのデストラクタを実行してスタックを実行し直します。
2番目の戦略では、この情報をスタック外のテーブルに移動します。これで、例外が発生すると、コールスタックを使用して、入力されたが終了されなかったスコープが検出されます。次に、それらは静的テーブルで検索され、スローされた例外が処理される場所と、その間に実行されるデストラクタが決定されます。これは、スタックの例外オーバーヘッドが少ないことを意味します。とにかくリターンアドレスが必要です。テーブルは追加のデータですが、コンパイラーはそれらをプログラムのデマンドロードセグメントに配置できます。
free()
またはが欠落しているCプログラムの数は誰もが知っていfclose()
ます。
これは、15.1標準の例外をスローすることで定義されています。
スローは一時オブジェクトを作成します。
この一時オブジェクトのメモリがどのように割り当てられるかは指定されていません。
一時オブジェクトの作成後、制御は呼び出しスタック内の最も近いハンドラーに渡されます。スローポイントとキャッチポイントの間のスタックを巻き戻します。スタックが巻き戻されると、スタック変数は作成の逆の順序で破棄されます。
例外が再スローされない限り、一時はキャッチされたハンドラーの最後で破棄されます。
注:参照でキャッチすると、参照は一時オブジェクトを参照します。値でキャッチすると、一時オブジェクトが値にコピーされます(したがって、コピーコンストラクターが必要です)。
S.Meyersからのアドバイス(const参照によるキャッチ)。
try
{
// do stuff
}
catch(MyException const& x)
{
}
catch(std::exception const& x)
{
}
あなたは見て可能性があり、ここで詳細な説明のため。
また、基本的な種類の例外処理を実装するためにプレーンCで使用されるトリックを確認することも役立つ場合があります。これには、setjmp()とlongjmp()を次のように使用する必要があります。前者は例外ハンドラー(「catch」など)をマークするためにスタックを保存し、後者は値を「スロー」するために使用されます。「スローされた」値は、呼び出された関数から返されたように見えます。「tryブロック」は、setjmp()が再度呼び出されたとき、または関数が戻ったときに終了します。
これは古い質問ですが、gccとVCのそれぞれで使用されている両方の方法を説明する非常に優れた説明があります:http://www.hexblog.com/wp-content/uploads/2012/06/Recon- 2012-Skochinsky-Compiler-Internals.pdf