mfc 中的 DLL 函数出错
Posted
技术标签:
【中文标题】mfc 中的 DLL 函数出错【英文标题】:Error with DLL functions in mfc 【发布时间】:2015-01-02 06:23:42 【问题描述】:我做了一个小应用程序,我在应用程序类的 Init 实例中加载了一个 DLL。下面提到的代码运行正常,但在发布模式下它正在崩溃。我使用 Visual Studio,DLL 位于应用程序的 Debug 和 Release 文件夹中。
typedef char BufType[4095];
typedef int (*QuickLicenseRT)(BufType);
BufType Buf;
QuickLicenseRT pQuickLicense;
HINSTANCE QL_Lib;
char* Message;
int i, BufSize;
BOOL CDemo::InitInstance()
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
QL_Lib = LoadLibrary(_T("QuickLicenseRuntime.dll"));
pQuickLicense = (QuickLicenseRT)GetProcAddress(QL_Lib, "QuickLicenseRT");
Message = "ABC";
BufSize = strlen(Message);
for(i=0; i<BufSize; i++)
Buf[i]= Message[i];
Buf[BufSize] = 0;
MessageBox(NULL, _T("before pQuickLicense (Buf)"), _T("Message"), MB_OK);
(pQuickLicense)(Buf); // here it is crashing
MessageBox(NULL, _T("after pQuickLicense (Buf)"), _T("Message"), MB_OK);
ResponseMessage = Buf;
return TRUE;
我在一些语句之后放置了一些消息框。我注意到在 (pQuickLicense)(Buf) 处,它正在崩溃。加载 QuickLicenseRuntime.dll 后,我得到了函数的地址。我不明白哪里错了。
谢谢
【问题讨论】:
总是检查你的LoadLibrary()
GetProcAddress()
调用的结果——如果它们不是NULL,那么崩溃是在QuickLicenseRT()
逻辑(在DLL中),你可能需要构建一些可选的诊断日志以查看崩溃的位置;调试版本和发布版本之间的主要区别之一是指针初始化...
【参考方案1】:
Buf[BufSize] = 0;
已经写出 Buf 区域,理论上会损坏 pQuickLicense —— 实际上它不应该因为填充而造成伤害。 Buf[BufSize-1] = '\0';
会更合适。
您还可以修改 typedef int (*QuickLicenseRT)(BufType);
以定义调用约定,即 __cdecl 或 FAR PASCAL。使用错误的调用约定可能会损坏您的数据内存。
一般来说,您的编程风格可能会受益于考虑一些有关 C++ 的基本知识,即 Kerningham 和 Ritchie “用 C 编程”。
【讨论】:
鉴于代码逻辑,Buf[BufSize-1]='\0'
将错误地截断字符串。不管怎样,由于BufSize
是从不相关的数据推导出来的,因此使用BufSize
或BufSize-1
作为索引同样是错误的。动态大小的数组,如std::vector
将解决所有问题。然而,缺少的调用约定将是崩溃的主要候选者。函数指针类型应该可以通过库附带的头文件获得。
@Girish:您使用 strlen 而不是 sizeof 编辑了问题中的代码,让我困惑了一分钟。新代码Message = "ABC"; BufSize = strlen(Message); Buf[BufSize] = 0;
只是在它已经存在的地方写入一个 '\0' 字符,因为strlen()
只是对字符进行计数,直到找到一个空字符。如果你真的需要初始化缓冲区,try Buf[0] = 0 or memset(Buf, 0, sizeof(Buf));
。如果只想复制字符串,单行strcpy(Buf, Message);
就足够了。
这是不正确的。复制字符的循环具有i<BufSize
的终止条件,实质上是在零终止符之前 停止。因此Buf[BufSize]=0
是强制性的。显然,strcpy
更易于使用,因为它已经处理了零终止符。不过,它也无法避免缓冲区溢出。
@IInspectable:假设在 Buf[3] 处为空字符,您错过了从 strlen(Buf) 派生的 BufSize (3)。
我很清楚 source 字符串有一个零终止符。但是,缓冲区副本没有,Buf[BufSize]=0
是强制性的。 Buf
是一个本地对象,因此不是零初始化的。这不是具有静态存储持续时间的对象(将被零初始化)。编辑:我假设 Buf
是一个本地对象。它不是(无论出于何种原因),也不需要Buf[BufSize]=0
。以上是关于mfc 中的 DLL 函数出错的主要内容,如果未能解决你的问题,请参考以下文章
MFC 里 CMFCPropertyGridCtrl 执行 DeleteProperty 出错
在 Visual Studio 中使用 cygwin 编译的 dll 的库函数时出错