windows下loadlibrary加载dll最简流程为:调用loadlibrary获取模块句柄→用getprocaddress获取函数地址→强制转换为对应函数指针类型后调用→最后调用freelibrary释放资源;漏掉任一环节可能导致崩溃或内存泄漏。

Windows下用LoadLibrary加载DLL最简流程
直接调用 .dll 文件必须走 Windows API,C++ 本身不提供跨平台的动态库加载语法。核心就是三步:加载 → 获取函数地址 → 调用 → 释放。漏掉任意一步都可能崩溃或内存泄漏。
常见错误是把 LoadLibrary 返回值当函数指针用,其实它返回的是模块句柄(HMODULE),得再用 GetProcAddress 提取具体函数。
- 确保
.dll在当前目录、系统路径或PATH环境变量里,否则LoadLibrary返回NULL - 函数名要和 DLL 导出的实际符号完全一致(注意 C++ 名字修饰问题,建议导出时用
extern "C") - 调用前必须强制转换为对应函数签名类型,否则参数压栈错位,轻则结果异常,重则程序崩溃
如何正确声明和调用导出函数
DLL 里导出的函数如果用了 C++ 编译,默认会做名字修饰(name mangling),导致 GetProcAddress 找不到原始函数名。所以 DLL 源码里得显式控制导出方式:
extern "C" __declspec(dllexport) int add(int a, int b) {
return a + b;
}
这样导出的函数名就是裸的 add,不是类似 ?add@@YAHHH@Z 的修饰名。客户端代码中需定义匹配的函数指针类型:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
typedef int (*AddFunc)(int, int)声明类型别名 - 调用
GetProcAddress(hModule, "add")后,必须reinterpret_cast<addfunc>(addr)</addfunc>转换,不能直接赋值 - 若 DLL 导出的是类成员函数或模板实例,无法直接通过
GetProcAddress调用——它们没有稳定符号名
静态链接 .lib 和动态 LoadLibrary 的区别在哪
很多人混淆“隐式链接”(链接 .lib)和“显式加载”(LoadLibrary)。前者在进程启动时由系统自动加载 DLL,后者在运行时手动控制。
隐式链接看似简单,但要求 DLL 必须存在且版本兼容,否则程序根本起不来;显式加载能做容错处理,比如降级逻辑或提示用户安装缺失组件。
- 隐式链接需要头文件 +
.lib+.dll,编译期绑定,无法绕过 DLL 缺失错误 - 显式加载只需
.dll,运行期决定是否加载,适合插件机制或可选功能模块 - 混合使用危险:
LoadLibrary加载的 DLL 若和隐式链接的同名 DLL 冲突,可能导致符号解析混乱
常见崩溃点和调试技巧
最常踩的坑是忘记调用 FreeLibrary,或者在 DLL 卸载后还继续调用其函数。更隐蔽的问题是线程安全:同一个 HMODULE 可被多线程共用,但 FreeLibrary 不能乱调——它只是减少引用计数,只有归零才真正卸载。
- 每次
LoadLibrary都应配对FreeLibrary,尤其在循环或反复加载场景下 - 用
GetLastError()查错误码,比如ERROR_MOD_NOT_FOUND(找不到 DLL)、ERROR_PROC_NOT_FOUND(函数名不对) - 用 Dependency Walker 或
dumpbin /exports xxx.dll确认实际导出符号名,避免拼写/大小写/调用约定(__cdeclvs__stdcall)不一致
导出函数的调用约定必须和客户端一致,否则栈清理错乱。默认 __cdecl,但 Windows API 多用 __stdcall,看 DLL 文档或用工具验证最可靠。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










