今天碰到一个头疼的问题,从网上下载一个动态库,在动态加载使用的时候报莫名其妙的异常,而且catch(Exception& e)无法捕获;而且只在release模式下使用该库出错,在debug模式下不报错,所以无法调试,只能在release模式下在程序中通过记录日志进行跟踪。通过日志最后发现调用过库内函数后,调用函数的栈内变量竟然被修改了,百思不得其解。最后通过review代码发现,原使用动态库函数代码如下:
bool __stdcall (*DllMethods)(LPCTSTR,LPCTSTR);
HINSTANCE hInst=NULL;
hInst=LoadLibrary((ExtractFilePath(Application->ExeName)+"ZLibWrap.dll").c_str());
FARPROC P;
P = GetProcAddress(hInst,(char*)DoZip.c_str());
DllMethods=(bool __stdcall (__cdecl *)(LPCTSTR,LPCTSTR))P;
动态库中的函数声明的是C语言调用约定(__cdecl),而我使用的时候竟然使用的是C++调用约定(__stdcall)。找到原因后,代码修改后如下所示:
bool __cdecl (*DllMethods)(LPCTSTR,LPCTSTR,bool);//必须使用C语言调用约定,否则调用函数可能修改栈内变量
HINSTANCE hInst=NULL;
hInst=LoadLibrary((ExtractFilePath(Application->ExeName)+"ZLibWrap.dll").c_str());//动态加载DLL
FARPROC P;
P = GetProcAddress(hInst,(char*)DoZip.c_str());
DllMethods=(bool (__cdecl *)(LPCTSTR,LPCTSTR,bool))P;
然后再次release下运行程序,一切顺利!!!