VC6-DLL与BCB5-EXE连结运行时静态库函数似乎存在问题?

类别:编程语言 点击:0 评论:0 推荐:

关于VC6-DLL与BCB5-EXE连结运行时静态库函数存在问题的研究


测试环境:

XP-Pro + VC6/SP5/SP6 + BCB5/UPD


问题现象:

以前在BCB5上开发了script.dll,并与BCB5同平台上开发的hce.exe运行很稳定,没有发现什么明显问题。

本月测试了STL/Boost相关内容,随便改造了script.dll,主要是更换本人自行开发容器模板为STL类型,由于仅更换了容器模板,算法本身未作什么大的更改,因此计算结果应与现有的数据完全一致。

经过简单的表达式和脚本测试,结果无误,并发布了一个免费的计算器程序,以进行更广泛的公开测试。

为了进行大数据量测试,本人将其与原BCB5开发的 hce.exe 动态连接运行(即:替换原BCB5开发的script.dll库),突然发现计算结果不甚一致,有一定的误差,虽然不大,但理论上不应有任何不同。

于是深入分析了一下script.dll与hce.exe的源代码,结果发现hce.exe中格式化数据的函数是sprintf,但sprintf函数在与两种开发工具产生的 script.dll 动态连接运行时,得到的结果不一样!!!!

比如:浮点数0.031025,在程序中需要保留5位小数,hce.exe+BCB版DLL得到的结果为0.03103,而hce.exe+VC6版得到的结果却为0.03102。很明显VC6版存在一定的问题。

为了搞清楚原因,先是google了“四舍五入”,发现有一种“四舍六入五成双”的算法,确实后者更为科学一些。但后来又发现VC6版DLL中对 0.001105 取5位小数得到的结果为 0.00111,很显然也不符合“四舍六入五成双”。

但一想VC6也不简单,怎么会犯这么低级的错误。于是动手写了个测试程序,用VC6-CL.exe编译运行

#include <cstdio>
void main(void)
{
printf("%.*f\n", 5, 0.031025);
}

得到结果为:0.03103,很正确! 可见VC6本身没有这个问题。再用BCB5编译,结果同样正确。说明二者独立运行时没有这样的问题。

于是开始怀疑,VC6版的DLL与BCB5版的EXE动态连结运行时,存在某种潜在的“库”连结问题!

这了验证这个猜测,于是考虑设计两个简单的示例程序,一个将在VC6下编译为script.dll文件,其中随便export一个函数即可。另一个将在BCB5下编译为.exe文件,并动态载入前面这个script.dll,并在载入点前后用相同的源代码向std::cout打印结果。

下面是DLL测试程序(script.cpp):

#include "windows.h"
#include
int WINAPI DllEntryPoint(HINSTANCE hinstDLL, unsigned long fdwReason, void * lpvReserved)
{
hinstDLL;fdwReason;lpvReserved;return TRUE;
}
#define DLLEXPORT __declspec( dllexport ) DLLEXPORT int __stdcall __dll_func()
{
char buf[64]; memset(buf,0,sizeof(buf));
sprintf(buf, "%.*f\n", 5, 0.031025);
return 0;
}

用VC6的命令行编译

cl.exe /LD script.cpp

得到 script.dll 文件

下面是EXE测试程序script_test.cpp:

#include <cstdio>
#include <iostream>
#include <cmath>
int main(void)
{
char buf[64]; memset(buf,0,sizeof(buf));

sprintf(buf, "%.*f\n", 5, 0.031025); //得到0.03103
std::cout

本文地址:http://com.8s8s.com/it/it23696.htm