使用GetProcAddress()无法从DLL加载函数的问题排查求助
问题原因及解决方法
你遇到的GetProcAddress返回NULL的核心原因是:DLL中的Monitoring函数没有被正确导出,导致导出表中没有你要查找的"Monitoring"函数名。
具体问题点
在Library.h中,你定义了MY_DLL_API宏来标记导出/导入函数,但Monitoring和NoSynchroSum的函数声明并没有使用这个宏。这意味着:
- 编译DLL时,这两个函数不会被标记为
_declspec(dllexport),也不会应用extern "C"来避免C++名字修饰。 - 最终DLL的导出表中,
Monitoring函数会被C++编译器修改为带修饰的名字(比如?Monitoring@@YAXH@Z),而你调用GetProcAddress(hInstance, "Monitoring")用的是原函数名,自然找不到。
修复步骤
- 修改Library.h中的函数声明,给需要导出的函数加上
MY_DLL_API宏:
#pragma once #include <iostream> #include <windows.h> #include <string> #include <cmath> using namespace std; #ifdef MY_DLL_EXPORTS #define MY_DLL_API extern "C" _declspec(dllexport) #else #define MY_DLL_API extern "C" _declspec(dllimport) #endif struct args { int Elements; int sum; int* Array; }; MY_DLL_API DWORD WINAPI NoSynchroSum(LPVOID); MY_DLL_API void Monitoring(int);
重新编译DLL项目,确保新的DLL包含正确的导出函数。
验证位数一致性:确保调用程序和DLL的编译位数一致(都是x64或都是x86)。你的调用代码中加载的是x64 Debug版本的DLL,需要确保调用项目的编译目标也是x64。
额外的代码问题提醒
你的Monitoring函数中存在线程安全问题:
- 创建线程后直接调用
CloseHandle,但线程可能还未执行完成,此时就删除了Array和_args,会导致线程访问已释放的内存,引发未定义行为。 - 正确的做法是调用
WaitForSingleObject(handle, INFINITE)等待线程执行完毕后,再释放资源并关闭句柄:
void Monitoring(int Elements) { int ElementsAmount = Elements; HANDLE handle; int sum = 0; srand(time(0)); int* Array = new int[ElementsAmount]; for (int i = 0; i < ElementsAmount; i++) { Array[i] = rand() % 21 - 10; } args* _args = new args; _args->Elements = ElementsAmount; _args->sum = sum; _args->Array = Array; handle = CreateThread(NULL, 0, NoSynchroSum, (LPVOID)_args, NULL, NULL); // 等待线程执行完成 WaitForSingleObject(handle, INFINITE); // 此时sum已经被线程更新 cout << "Counted Sum = " << _args->sum << endl; CloseHandle(handle); delete[] Array; delete _args; }
内容的提问来源于stack exchange,提问作者fuvaji
相关产品推荐
相关产品推荐

