失敗した場合に例外が発生するコードを単体テストする必要があります。簡単に言えば、スタック フレームをアンワインドするか、エラーをローカル ジャンプして、例外を処理する必要があります。MSVC の使用はオプションではありません。
AddVectoredExceptionHandlerのMSDN の例は、eip を変更してから EXCEPTION_CONTINUE_EXECUTION を返してローカル ジャンプを実行できることを示しています。明らかな問題は、どのアドレスにジャンプするかです。GCC のLabel as Value機能は、まさにそのように思われます。
以下の例は、エラーが発生した関数から単一の戻り値がある場合に機能します。ただし、2 番目の return ステートメントが追加されると、ジャンプのオフセットが疑わしいほど小さくなり、ジャンプは失敗します。なんで?
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0502
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static bool handler_called;
static DWORD handler_eip;
static LONG WINAPI local_handler(struct _EXCEPTION_POINTERS* ExceptionInfo) {
handler_called = true;
PCONTEXT Context = ExceptionInfo->ContextRecord;
Context->Eip = handler_eip;
return EXCEPTION_CONTINUE_EXECUTION;
}
static void badcall(void) {
handler_called = false;
handler_eip = &&fail;
int value = 100;
int zero = 0;
value = value/0;
printf("not handled.\n");
assert(false);
//return; // Uncomment this to break the handler
fail:
printf("error handled.\n");
return;
}
int main(int argc, char* argv[]) {
void* old_handler = SetUnhandledExceptionFilter(&local_handler);
badcall();
SetUnhandledExceptionFilter(old_handler);
return(0);
}