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 是从不相关的数据推导出来的,因此使用BufSizeBufSize-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&lt;BufSize 的终止条件,实质上是在零终止符之前 停止。因此Buf[BufSize]=0 是强制性的。显然,strcpy 更易于使用,因为它已经处理了零终止符。不过,它也无法避免缓冲区溢出。 @IInspectable:假设在 Buf[3] 处为空字符,您错过了从 strlen(Buf) 派生的 BufSize (3)。 我很清楚 source 字符串有一个零终止符。但是,缓冲区副本没有,Buf[BufSize]=0 是强制性的。 Buf 是一个本地对象,因此不是零初始化的。这不是具有静态存储持续时间的对象(将被零初始化)。编辑:我假设 Buf 是一个本地对象。它不是(无论出于何种原因),也不需要Buf[BufSize]=0

以上是关于mfc 中的 DLL 函数出错的主要内容,如果未能解决你的问题,请参考以下文章

构建节点 gyp 时出错

MFC 里 CMFCPropertyGridCtrl 执行 DeleteProperty 出错

在 Visual Studio 中使用 cygwin 编译的 dll 的库函数时出错

Python调用C++DLL函数出错String类型问题

MFC无法运行的原因?我在MFC中加入了一个CWebBrowser的控件后,运行没有出错,但是点击运行是却没有弹出窗

将 char 数组发送到 DLL 调用“不知道如何转换参数”时出错