Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从VBA调用dll函数时出现浮点错误_Vba_Dll_Overflow_Fpu - Fatal编程技术网

从VBA调用dll函数时出现浮点错误

从VBA调用dll函数时出现浮点错误,vba,dll,overflow,fpu,Vba,Dll,Overflow,Fpu,情况是这样的。我正在使用MS Visual Sturio 2005和Excel 2007。我创建了一个包含函数的dll extern "C" VARIANT WINAPI MyFunc() { VARIANT res; memset(&res, 0, sizeof(VARIANT)); ::VariantInit(&res); return res; } 这是从Excel VBA调用的。此功能似乎工作正常。 但有一个问题:当VBA从我的函数返回并尝试执行

情况是这样的。我正在使用MS Visual Sturio 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的项目包含4个文件:mydll.cpp、mydll.def、cSomeClass.cpp和cSomeClass.h

cSomeClass
是一个相当复杂的类,它从我的其他lib调用代码。但是
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;
}
#包括
#包括
BOOL APIENTRY DllMain(句柄模块、DWORD ul_原因、LPVOID LPREFERED)
{
返回TRUE;
}
外部“C”变量WINAPI MyFunc()
{
无符号整数u;
u=_-controlfp(0,0);
_控制FP(u&~(_EM_无效| u EM_非规范| u EM_零除| u EM_溢出| u EM_下溢| u EM_不精确),_MCW_EM);
变体res;
memset(&res,0,sizeof(VARIANT));
::VariantInit(&res);
返回res;
}
MyFunc()
的初始版本没有前3行(与
\u controlfp()
冲突的那3行),这导致了VBA中的
“运行时错误6,溢出”
。然后我开始怀疑这个错误可能与FPU寄存器有关(我对这些寄存器知之甚少)。当我添加这3行代码时,调用
\u controlfp()
-
“0xC0000090:浮点无效操作”时引发异常。
。如果我保留上面显示的代码,异常会导致堆栈展开(我们没有进入
VARIANT res;
行),Excel中会显示一个窗口,显示“运行时错误6.溢出”。。总而言之,添加这3行代码会导致先前抛出浮点异常。如果我们捕捉到在第三行抛出的异常(使用
\uuuException
子句)并忽略它(通过调用
\uClearFP()
),则Excel中不会报告任何错误

一个令人讨厌的细节:如果我从VisualStudio项目中删除文件
cSomeClass.cpp
cSomeClass.h
,则不会再现错误
cSomeClass.h
不包括在
mydll.cpp
中,但如果我从项目中删除
cSomeClass.*
文件,则dll大小会显著减小

我在这一点上的最佳猜测是,
cSineClass.cpp
引用的LIB-s中有一些静态对象导致了这种情况。可能在加载dll时(根据我的实验,在加载到
DllMain
之前)初始化(构造)了这些对象,这不知何故导致设置了
的错误标志“0xC0000090:浮点无效操作”。
。当我们从dll返回Visual Basic时,somethis调用
\u controlfp
,并在引发
“0xC0000090:浮点无效操作。”
时启用浮点异常(它们在С++中被关闭)。该异常以某种方式转换为我在Excel中看到的
“运行时错误6.溢出”。
。这只是一个猜测。到目前为止,我还没有发现任何静态对象可以这样做

不幸的是,我无法创建一个复制此错误的小示例,因为它仅在我将
cSomeFile.*
作为项目的一部分时才会显示。那些文件需要我所有的库

如果有人知道这种行为的原因或对如何推进我的调查提出建议,我们将不胜感激。

1)显然,当我从VBA进入DLL代码时,FPU异常被关闭,就像有人调用

  u = _controlfp( 0, 0 );
  _controlfp( u & ((_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT )), _MCW_EM );
在将控制传递给我的dll代码之前

2) 在任意点调用std::numeric_limits::signaling_NaN()会导致在浮点状态字中设置_EM_INVALID标志(可以通过调用_statusfp()看到)

3) 当控件从DLL返回时,FPU异常似乎已打开。好像有人打电话来:

  u = _controlfp( 0, 0 );
  _controlfp( u & (~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | EM_UNDERFLOW | _EM_INEXACT )), _MCW_EM );

这会导致运行时错误。

因此,我在不同的时候都遇到了类似的Excel随机问题,而你是我的英雄


我发现通过调用
\u clearfp()
,它将消除错误并正确返回值。我认为这个问题是因为我使用了大量的值来表示无效的浮动。设置标志,并导致Excel(仅Excel)呕吐。我以前从未在任何其他程序中遇到过运行时异常问题。

OK。我已经缩小了范围。它是由一个静态常量双变量在_CRT_INIT()中用numeric_limits::infinity()初始化引起的,该函数在DllMain之前调用。有人能解释一下这里发生了什么吗?谢谢很抱歉,这似乎是由另一个变量用numeric_limits::signaling_NaN()初始化引起的。您知道如何解决此问题吗?我有完全相同的问题。