Windows SEH で無効な浮動小数点演算を報告するために使用する未処理の例外フィルター (SetUnhandledExceptionFilter() を参照) を作成しようとしています。例外をトラップし、スタック トレースを出力してから、浮動小数点例外を無効にし、結果の非有限値または非数値値で実行を再開したいと考えています。
例外をキャッチして実行を再開する機能を示すために、以下の簡単なプログラムを作成しました。#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 の浮動小数点コンテキストを正しく設定する方法について何か考えはありますか?
前もって感謝します