これが状況です。MS Visual Strio 2005 と Excel 2007 を使用しています。関数を含む dll を作成します。
extern "C" VARIANT WINAPI MyFunc()
{
VARIANT res;
memset(&res, 0, sizeof(VARIANT));
::VariantInit(&res);
return res;
}
これは、Excel VBA から呼び出されます。この機能は正しく動作しているようです。しかし、問題があります。VBA が関数から戻り、次の浮動小数点命令を実行しようとすると、次のウィンドウが表示されます。
実行時エラー 6. オーバーフロー。
このエラーはかなり奇妙です。私はここ数日それを調査してきました、ここに私が集めた「事実」があります:
1) エラーは、dll への最初の呼び出しの後にのみ表示されます。この関数を連続して呼び出しても、このエラーは発生しません。
2) エラーは、コントロールが dll から戻った後、VBA コード内の最初の (一見無害な) 浮動小数点命令によってトリガーされます。
Dim dMinValue As Double
dMinValue = 10000000#
3) dll のビルド元のプロジェクトには、mydll.cpp、mydll.def、cSomeClass.cpp、および cSomeClass.h の 4 つのファイルが含まれています。
cSomeClass
私の他のライブラリからコードを呼び出すかなり複雑なクラスです。しかし、mydll.cpp
決して使用cSomeClass
しません。のコードは次のmydll.cpp
とおりです。
#include <OAIdl.h>
#include <float.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
extern "C" VARIANT WINAPI MyFunc()
{
unsigned int u;
u = _controlfp(0, 0);
_controlfp(u & ~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT), _MCW_EM);
VARIANT res;
memset(&res, 0, sizeof(VARIANT));
::VariantInit(&res);
return res;
}
の初期バージョンにMyFunc()
は最初の 3 行 ( をいじっているもの) がなく、VBA_controlfp()
で発生していました。"Runtime Error 6, Overflow"
次に、このエラーが FPU レジスタに関連している可能性があるのではないかと疑い始めました (それらについてはほとんど知りません)。_controlfp()
これらの 3 行を追加すると、 - を呼び出すと例外がスローされました"0xC0000090: Floating-point invalid operation."
。コードを上に示したままにしておくと、例外によってスタックが巻き戻され (行に到達しません) 、Excel にVARIANT res;
ウィンドウが表示されます。"runtime error 6. Overflow."
まとめると、これらの 3 行を追加すると、浮動小数点例外が先にスローされます。3 行目でスローされた例外を (__except
節で) キャッチし、それを ( callng で_clearfp()
) 無視すると、Excel でエラーは報告されません。
厄介な詳細: ファイルを削除cSomeClass.cpp
しcSomeClass.h
、Visual Studio プロジェクトからエラーが再現されません。cSomeClass.h
には含まれていませんが、プロジェクトからファイルmydll.cpp
を削除cSomeClass.*
すると、dll のサイズが大幅に縮小されます。
この時点での私の最善の推測は、これによって参照される LIB-s にいくつかの静的オブジェクトがあるcSineClass.cpp
ということです。おそらく、これらのオブジェクトは、dll がロードされているときに初期化 (構築) され (私の実験によると、前にDllMain
)、これによりエラーフラグ"0xC0000090: Floating-point invalid operation."
が設定されます。dll から Visual Basic に戻ると、somethis は_controlfp
浮動小数点例外を呼び出して有効にします (С++ では無効になっています) 。発生が Excel で見られるものに"0xC0000090: Floating-point invalid operation."
何らかの形で変換されます。"Runtime Error 6. Overflow."
これは単なる推測です。これまでのところ、これを実行できる静的オブジェクトは見つかりませんでした。
残念ながら、このエラーを再現する小さな例を作成できませんでした。これcSomeFile.*
は、プロジェクトの一部としてのみ表示されるためです。そして、それらのファイルにはすべてのライブラリが必要です...
誰かがそのような行動の原因を知っている場合、または私の調査を進める方法について提案がある場合は、大歓迎です.