LoadLibrary返回NULL需先调用GetLastError获取错误码(如126表示模块未找到),再检查DLL路径是否为绝对路径、位数是否匹配(32/64位)、依赖项是否完整(可用Dependencies工具扫描),并确保使用LoadLibraryW处理Unicode路径。

LoadLibrary 返回 NULL 怎么排查
调用 LoadLibrary 返回 NULL 是最常见问题,本质是系统找不到或无法加载目标 DLL。不是代码写错,而是路径、依赖、位数或权限出了问题。
- 先用
GetLastError()获取错误码,再查 Windows 错误码文档,比如126(ERROR_MOD_NOT_FOUND)表示找不到 DLL 或其某个依赖项 - DLL 路径必须是绝对路径,相对路径会按 Windows 搜索顺序找(当前目录、System32、PATH 等),极易失败;推荐用
GetFullPathName转成绝对路径再传给LoadLibrary - 32 位程序只能加载 32 位 DLL,64 位同理;混用会导致
LoadLibrary静默失败(GetLastError返回193,即ERROR_BAD_EXE_FORMAT) - 检查 DLL 是否依赖其他 DLL(如 Visual C++ 运行库、OpenSSL 等),可用
Dependencies工具(替代旧版 Dependency Walker)扫描缺失项
GetProcAddress 获取函数地址时崩溃或返回 NULL
GetProcAddress 返回 NULL,通常不是函数名写错就是导出方式不匹配——C++ 编译器默认对函数名做 C++ name mangling,而 GetProcAddress 只认 C 风格的未修饰名。
- 确保 DLL 中导出函数用
extern "C"声明,例如:extern "C" __declspec(dllexport) int add(int a, int b) { return a + b; } - 导出函数名必须和
GetProcAddress传入的字符串完全一致(区分大小写),可用dumpbin /exports your.dll查看实际导出名 - 不要直接把函数指针当普通函数调用;必须先定义函数类型别名,再强制转换:
typedef int (*AddFunc)(int, int);
AddFunc pAdd = (AddFunc)GetProcAddress(hMod, "add");
if (pAdd) result = pAdd(2, 3); - 若 DLL 导出的是类或成员函数,不能直接用
GetProcAddress;应导出工厂函数(如CreateInstance),返回接口指针
FreeLibrary 后继续调用函数导致崩溃
FreeLibrary 卸载 DLL 后,所有通过 GetProcAddress 获取的函数地址立即失效。此时调用它们属于野指针行为,大概率触发访问冲突(0xC0000005)。
- 卸载前务必确保所有相关函数调用已结束,且无任何线程仍在执行该 DLL 中的代码
- 不要在 DLL 的导出函数内部调用
FreeLibrary(this_module)(即“自卸载”),Windows 不允许,会引发未定义行为 - 如果 DLL 被多次
LoadLibrary,需对应次数的FreeLibrary才真正卸载;可用GetModuleHandle判断是否已加载,避免重复加载 - 建议封装一个 RAII 类管理
HMODULE生命周期,构造时LoadLibrary,析构时FreeLibrary,防止遗漏
Unicode 路径下 LoadLibraryW 失败但 LoadLibraryA 成功
Windows 中 LoadLibrary 是宏,ANSI 版(LoadLibraryA)无法正确处理含中文或特殊字符的路径,尤其在非系统 locale 下容易截断或乱码,导致找不到文件。
立即学习“C++免费学习笔记(深入)”;
- 一律使用宽字符版本:
LoadLibraryW,传入LPCWSTR(即const wchar_t*) - 路径字符串必须以
L前缀声明,或用MultiByteToWideChar转换 UTF-8 路径(如从命令行或配置文件读取) - 确认项目字符集设置:VS 中若设为 “Use Multi-Byte Character Set”,
LoadLibrary宏会指向A版本,需显式调用LoadLibraryW -
SetCurrentDirectoryW不影响LoadLibraryW的路径解析逻辑,别指望切工作目录来绕过绝对路径要求
vcruntime140.dll,LoadLibrary 就会静默失败,而错误码还可能被中间层覆盖。动手前,先用 Dependencies 扫一遍,比反复改代码快得多。










