2017-01-27 3 views
0

私はVishal Kochharの優れたarticleに、C++コンパイラがどのように例外処理を実装したかについて基本的な考え方を持っています。 try/catch構文は、関数に表示されたときに、基本的に、コンパイラはこのように、プロローグ/エピローグコードを生成します:質問がある暗黙的な例外処理

push -1 
push offset new_handler 
mov eax, fs:[0] 
push eax ; old handler saved on the stack 
mov fs[0], esp 
... 
mov ecx, [ebp-0Ch] ; recover old handler 
mov fs[0], ecx 

を、このようなものは、コンパイラによって挿入された理由は何ですか一見例外処理とは何の関係もない関数に変換しますか?ソースコードによれば、自分の体にtry/catchブロックは存在しないと確信しています。

+3

範囲外になったときに「自動的に」解放する必要がある管理対象タイプのために挿入される暗黙的なtry/catchフレームがあることがあります。 –

+0

C++コードと生成されたアセンブリコードの間にiff関係はありません。あなたが見ているコードパターンが、C++ソースのtry/catch構造のインジケータではないことは、暗黙的であるかどうかにかかわらず、複数の上位レベルの構造をサポートするために使用できるパターンに過ぎません。 –

+0

例外は、スローポイントとキャッチポイントの間で呼び出される関数を通過し、途中でクリーンアップ(自動保存期間のデストラクタでオブジェクトを正しい順序でクリーンアップするなど)する必要があります。介入する機能で何かをしなければ、これを実現させる実際的な方法はありません。 – Peter

答えて

1

"これらの関数は"例外処理とはまったく関係がありません "というのは、ローカル変数のfinalisers/destructorsを実行している可能性があります。オブジェクトのファイナライザーは、通常の戻り値かキャッチされない例外かによって、スコープが終了するとすぐに実行する必要があります。したがって、関数は例外ハンドラーをプロローグにインストールしてファイナライザーが呼び出されるようにする必要があります。

この動作をトリガーするためにDでの簡単な例:

struct Foo { 
    ~this() { 
     ; 
    }; 
}; 

int main() { 
    Foo x; 
    return 0; 
}; 

おそらくスマートコンパイラはnothrow関数などでプロローグ/エピローグを省略することができるだろう:

struct Foo { 
    ~this() nothrow { 
     ; 
    }; 
}; 

int main() nothrow { 
    Foo x; 
    return 0; 
}; 

しかし、この言語ではないようです。