显式调用dll文件中的函数居然crash了

本文探讨了在Windows环境下,使用不同编译器(Mingw与MSVC)调用DLL文件中函数的问题。重点分析了一种随机崩溃的现象,通过详细审查代码和调试过程,发现函数调用约定关键字__stdcall的重要性。文章强调了在更换编译器时,理解并正确使用特定于编译器的语法约定的必要性。

windows系统下,调用dll文件里的函数,无非2种方法,一种就是直接包含头文件,编译连接dll文件对应的lib文件。另外一种,就是显式调用:在代码里load这个dll文件,声明函数指针,并绑定DLL文件里的某函数。

背景

显式调用在编程时,还是有很多使用场景的。比如说,需要同时调用2个厂家的SDK库函数,无奈的很,这2个SDK离大部分函数居然是同名的,传参数也相同,甚至API的作用都是一致的。大家估计想起了山寨,嘿嘿。动态load不同的dll文件,调用API的过程都是相同的,在这个情况下使用显示调用无疑是比较好的方法。

使用了QT里的API接口,注意:此接口在MINGW编译器下,都是正常工作的,但是更换MSVC的编译器后就不正常了。

QLibrary lib("xxxx.dll");

现象

此次显式调用API时,居然出现随机CRASH了。确实是随机crash,CDB显示的信息是指针越界了。调试很多次,但是几乎每次死的地方都不一样。

review代码,开始分析。
1. 检查了dll文件的load,返回值正常;
2. 检查函数绑定,似乎也正常;

FUNC func = (FUNC)lib.resolve("func");

3. 检查函数指针的声明

/* wrong */
typedef DWORD (*VCI_OpenDevice)(DWORD, DWORD, DWORD);

/* correct */
typedef DWORD (__stdcall *VCI_OpenDevice)(DWORD, DWORD, DWORD);

发现问题,关键字__stdcall丢失了,询问了下,为什么去掉了__stdcall。答曰,编译不过,所以去掉了。此关键字__stdcall添加后,调用正常了。

总结

Mingw编译器和MSVC编译器,对语法的约定要求上有一些不同。更换编译器后,不能因为编译报错,就简单粗暴的去掉某一些关键字,而应该多研究语法的异同。否则带来的调试工作,可能是灾难性的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值