【发布时间】:2013-04-24 02:31:03
【问题描述】:
我需要对一些失败案例引发异常的代码进行单元测试。简而言之,我需要通过展开堆栈帧或本地跳过错误来处理异常。不能使用 MSVC。
AddVectoredExceptionHandler 的MSDN example 表示我可以修改eip,然后返回EXCEPTION_CONTINUE_EXECUTION 进行本地跳转。显而易见的问题是要跳转到什么地址。 GCC 的 Label as Value 功能似乎应该就是这样。
如果错误函数只有一次返回,则下面的示例有效。但是,如果添加第二条 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);
}
【问题讨论】:
-
这段代码的反汇编你看了吗?注意到那里有什么奇怪的东西吗?