分享
 
 
 

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

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

关于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

HINSTANCE _hInst=::LoadLibrary("script.dll");//只需要load一下dll,不需调用任何函数

sprintf(buf, "%.*f\n", 5, 0.031025); //得到0.03102 !!!!!

std::cout

::FreeLibrary(_hInst);

return 0;

}

用BCB5命令行编译

bcc32 script_test.cpp

得到 script_test.exe 文件

然后运行 script_test.exe ,得到结果却为:

0.03103

0.03102

测试结果与预料的结果完全一致! 可见现在已经找到了问题重现的方法。

为了进一步测试,将两个.cpp文件交换编译器再进行测试,即互换编译器,BCB5产生DLL,VC6产生EXE,然后运行,结果为:

0.03103

0.03103

是正确的!

再次交换顺序,即用同一种编译器分别生成两套.dll与.exe,再运行,均得到正确的结果。

由此可见,问题应在VC6产生的DLL身上,因为只有VC6产生的DLL与BCB5产生的EXE无法正确运行(而反之则行)。

现在开始从VC6制造DLL的选项入手,看看是否能通过编译选项解决这个问题。

首先在VC6的命令行上加上编译选项 /MT,静态连接,

cl.exe /LD /MT script.cpp

生成script.dll,用BCB5生成的.exe测试,结果还是不正确。

再换 /MD 选项,

cl.exe /LD /MD script.cpp

生成script.dll,用BCB5生成的.exe一测试,结果正确了!!!!!这正是期望看到的结果。

看来问题就出在这里了。根据以上复杂的组合过程可以得到以下结论:

1、VC6生成的.dll与BCB5生成的.exe动态连结运行时,可能会引起sprintf()等函数运行不正常。

2、鉴于以上问题,有可能 stdio.h 中描述的函数如sprintf()在该情况下均可能出问题。

3、为了避免这个问题,在VC6的dll编译选项中必须添加上 /MD 选项。

其实本人在这里还是存在一些疑问,比如:在loadlibrary()载入.dll后,怎么会直接影响到.exe中的静态库函数呢?

由于目前时间和精力水平有限,没有继续深入。目前只能记住存在这样的问题及相应的解决方法。在此作个记录,以免日后忘了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有