我有一个从DLL导出的C ++代码。
DWORD WINAPI MessageBoxThread(LPVOID lpParam)
{
MessageBox(0, L"Test", L"Test", 0);
return 0;
}
这就是我的称呼方式
typedef DWORD(*MessageBoxThread)(LPVOID);
int StartMessageBoxThread() {
MessageBoxThread ShowMessageBox;
HMODULE testModule = LoadLibrary(L"C:\\Users\\david\\COMServer.dll");
ShowMessageBox = (MessageBoxThread)GetProcAddress(testModule, "MessageBoxThread");
ShowMessageBox(NULL);
FreeLibrary(testModule);
return 0;
}
我在ShowMessageBox()行上的KernelBase.dll中引发了异常,该异常在写入内存位置时涉及访问冲突。
我不明白我在做什么错。两个Visual Studio项目都设置为Unicode,并且我知道使用L前缀表示宽字符串。
我可以调试并逐步进入DLL,可以看到函数的地址,因此调用该函数的代码看不到任何错误。
答案 0 :(得分:5)
typedef DWORD(*MessageBoxThread)(LPVOID);
原型与dll中的定义不匹配。默认情况下,此处的调用约定为__cdecl
,而WINAPI
为__stdcall
typedef DWORD(WINAPI *MessageBoxThread)(LPVOID);
具体来说,在被调用端,由于约定为__stdcall
(被调用者清除堆栈),因此该函数将参数弹出堆栈。在调用者端,它看到约定为__cdecl
(调用者清除了堆栈),并且还从堆栈中弹出了参数,最终破坏了堆栈。
答案 1 :(得分:3)
在您的StartMessageBoxThread()
代码中,MessageBoxThread
的声明不正确。具体来说,它缺少调用约定,因此它使用编译器的默认约定,通常是__cdecl
而不是__stdcall
(WINAPI
映射到的)。调用约定不匹配是崩溃,调用堆栈损坏等常见原因。
此外,该代码完全没有错误检查。
尝试以下方法:
typedef DWORD (WINAPI *MessageBoxThread)(LPVOID);
int StartMessageBoxThread()
{
HMODULE testModule = LoadLibrary(L"C:\\Users\\david\\COMServer.dll");
if (testModule)
{
MessageBoxThread ShowMessageBox = (MessageBoxThread) GetProcAddress(testModule, "MessageBoxThread");
if (ShowMessageBox)
ShowMessageBox(NULL);
FreeLibrary(testModule);
}
return 0;
}