我正在尝试编写一个未处理的异常过滤器(请参阅 SetUnhandledExceptionFilter())以与 Windows SEH 一起使用以报告无效的浮点操作。我想捕获异常,打印堆栈跟踪,然后禁用浮点异常并使用生成的非有限或非数字值恢复执行。
我编写了下面的简单程序来演示捕获异常并恢复执行的能力。注意#ifdef _WIN64 的使用,因为 ContextRecord 的定义根据目标体系结构而变化(WIN32 使用“FloatSave”,WIN64 使用“FltSave”)。
#include "stdafx.h"
#include <float.h>
#include <Windows.h>
double zero = 0.0;
LONG WINAPI myfunc(EXCEPTION_POINTERS * ExceptionInfo){
/* clear the exception */
unsigned int stat = _clear87();
/* disable fp exceptions*/
unsigned int ctrl1 = _control87(_MCW_EM, _MCW_EM);
/* Disable and clear fp exceptions in the exception context */
#if _WIN64
ExceptionInfo->ContextRecord->FltSave.ControlWord = ctrl1;
ExceptionInfo->ContextRecord->FltSave.StatusWord = 0;
#else
ExceptionInfo->ContextRecord->FloatSave.ControlWord = ctrl1;
ExceptionInfo->ContextRecord->FloatSave.StatusWord = 0;
#endif
printf("#########Caught Ya#####!\n");
return EXCEPTION_CONTINUE_EXECUTION;
}
int _tmain(int argc, _TCHAR* argv[])
{
double a;
/* enable fp exceptions*/
_controlfp(0, _MCW_EM);
/* Setup our unhandled exception filter */
SetUnhandledExceptionFilter(myfunc);
/* do something bad */
a = 5.0 / zero;
printf("a = %f\n",a);
return 0;
}
当作为 WIN32 .exe 运行时,上述程序按预期运行,输出:
#########Caught Ya#####!
a = -1.#IND00
但是,当以 WIN64 .exe 运行时,程序进入死循环,不断重新捕获浮点异常:
#########Caught Ya#####!
#########Caught Ya#####!
#########Caught Ya#####!
#########Caught Ya#####!
#########Caught Ya#####!
#########Caught Ya#####!
...
这似乎表明我没有成功配置浮点单元,我想这与 WIN32 和 WIN64 之间 ContextRecord 的不同定义有关,但我还没有找到任何好的相关文档来确切说明如何设置浮点上下文。
关于如何正确设置 WIN64 的浮点上下文的任何想法?
提前致谢