这是我之前的asked yesterday
的后续问题问题出现在MSVS 2008 C ++ DLL中,该DLL有超过4000行代码,但我设法生成了一个简单的案例,演示了我的CPU(AMD Phenom II X6 1050T)上出现的问题。 / p>
它是否会显示另一个系统上发生的问题?我真的很想知道!
这是一个简单的类(Point.cpp),它需要编译为DLL:
#include <math.h>
#define EXPORT extern "C" __declspec(dllexport)
namespace Test {
struct Point {
double x;
double y;
/* Constructor for a Point object */
Point(double xx, double yy) : x(xx), y(yy) {}
/* Copy constructor */
Point(const Point &rhs) : x(rhs.x), y(rhs.y) {}
double mag() const;
Point norm() const;
};
double Point::mag() const {return sqrt(x*x + y*y);}
Point Point::norm() const {
double m = mag();
return Point(x/m, y/m);
}
EXPORT void __stdcall GetNorm(double x, double y, double *nx, double *ny)
Point P = Point(x, y);
Point N = P.norm();
*nx = N.x;
*ny = N.y;
}
}
这是测试程序(TestPoint.c),需要链接到为DLL创建的lib:
#include <stdio.h>
#define IMPORT extern __declspec(dllimport)
IMPORT void __stdcall GetNorm(double x, double y, double *nx, double *ny);
void dhex(double x) { // double to hex
union {
unsigned long n[2];
double d;
} value;
value.d = x;
printf("(0x%0x%0x)\n", value.n[1], value.n[0]);
}
double i64tod(unsigned long long n) { // hex to double
double *DP = (double *) &n;
return *DP;
}
int main(int argc, char **argv) {
double vx, vy;
double ux, uy;
vx = i64tod(0xbfc7a30f3a53d351);
vy = i64tod(0xc01b578b34e3ce1d);
GetNorm(vx, vy, &ux, &uy);
printf(" vx = %20.18f ", vx); dhex(vx);
printf(" vy = %20.18f ", vy); dhex(vy);
printf("\n");
printf(" ux = %20.18f ", ux); dhex(ux);
printf(" uy = %20.18f ", uy); dhex(uy);
return 0;
}
在我的系统上,使用VC ++编译TestPoint,输出为:
vx = -0.18466368053455054 (0xbfc7a30f3a53d351)
vy = -6.8354919685403077 (0xc01b578b34e3ce1d)
ux = -0.027005566159023012 (0xbf9ba758ddda1454,
uy = -0.99963528318903927 (0xbfeffd032227301b)
但是,如果使用 gcc 编译相同的代码,或者实际上,似乎任何等效的程序(例如VB6,PowerBasic),结果(ux和uy)都是微妙但绝对不同的(最后一个十六进制数字):
vx = -0.184663680534550540 (0xbfc7a30f3a53d351)
vy = -6.835491968540307700 (0xc01b578b34e3ce1d)
ux = -0.027005566159023008 (0xbf9ba758ddda1453)
uy = -0.999635283189039160 (0xbfeffd032227301a)
这似乎是一个微不足道的差异,但当它发生在物理引擎中时,这些差异会以惊人的方式累积。 。
如果引擎根据谁调用它会得到不同的结果,我可能不得不完全放弃使用VC ++并尝试使用 g ++ 。
答案 0 :(得分:1)
好的,我想我知道这是怎么发生的。看一下Point.dll的反汇编列表,我注意到GetNorm函数几乎是你所期望的,有几个FMUL和FDIV。 不的内容是FLDCW指令。
MSVC调用程序中也没有任何FLDCW,但我在调用程序的gcc和PowerBasic版本中都找到了FLDCW。
所以我调整了一个可执行文件(PowerBasic EXE最容易找到合适的地方进行调整),嘿,我接下来得到了与MSVC相匹配的答案。据推测,FLDCW改变了FPU舍入模式,因此最低有效位的差异。