書きかけ...と言うより書き残し orz ←Advanced Windows 等で詳しく述べられているが、自分が勘違いしていたのでおさらい。 |
Advanced Windows ではこれをグローバルアンワインドの中止
と称し、グローバルアンワインドを途中で終了させることが出来る
、とある。
void f1()
{
__try
{
::OutputDebugString("call f2().\n");
f2(); // 1.
}
__except (EXCEPTION_EXECUTE_HANDLER) // 4.
{
::OutputDebugString("f1() except handler.\n");
}
::OutputDebugString("f1() Leave.\n"); // 8.
}
void f2()
{
__try
{
::OutputDebugString("f2() __try.\n");
f3(); // 2.
}
__finally
{
::OutputDebugString("f2() __finally.\n"); // 7.
}
::OutputDebugString("f2() Leave.\n"); //
}
void f3()
{
__try
{
::OutputDebugString("f3() __try.\n");
strcpy(0,0); // 3.
}
__finally
{
::OutputDebugString("f3() __finally.\n"); // 5.
return; // 6.
}
::OutputDebugString("f3() Leave.\n"); //
}
となり、例外ハンドラが実行される前に f2() の finally ブロックが実行される。
これがグローバル アンワインドと呼ばれるもので、finally ブロックを処理してから例外ハンドラを実行する(finally ブロックが有れば)。
f1() の例外ブロックが実行されなくなった!
call f2(). ... #1
f2() __try. ... #5
f3() __try. ... #8
f3() __finally. ... #9
f2() __finally. ... #6
f2() Leave. ... #7
f1() Leave. ... #4
例外処理 (初回) は xxx.exe にあります: 0xC0000005: Access Violation。
もし、f3 の __finally 中の return が無ければ、
call f2(). ... #1
f2() __try. ... #5
f3() __try. ... #8
f3() __finally. ... #9
f2() __finally. ... #6
f1() exec handler.
f1() Leave. ... #4
例外処理 (初回) は xxx.exe にあります: 0xC0000005: Access Violation。
望み通り、例外が起きた後は __finally ブロックを呼び出して例外ハンドラへ進む。