跨平台动态库加载必须分平台实现:dlopen与loadlibrary在错误处理(dlerror/getlasterror需立即调用)、路径规则(linux不补后缀、windows自动加.dll)、符号查找(须extern "c"导出)、卸载逻辑(dlclose容错 vs freelibrary需验证句柄)及依赖解析时机(lazy vs 立即递归)均不兼容。

跨平台动态库加载不能靠“写一次、到处编译”蒙混过关——dlopen 和 LoadLibrary 表面相似,底层语义、错误机制、路径规则、符号解析逻辑全都不兼容。直接 typedef 一个统一句柄类型,等于主动放弃错误诊断能力。
错误信息必须立刻捕获,中间不能穿插任何系统调用
Windows 的 GetLastError() 和 Linux 的 dlerror() 都是“覆写式全局状态”,不是返回值。只要在 LoadLibrary 或 dlopen 后调了别的 API(比如 printf、malloc、甚至另一个 LoadLibrary),上一次的错误就丢了。
- Linux 下必须紧接
dlopen调用dlerror(),且只调一次:const char* err = dlerror();—— 第二次调就返回nullptr - Windows 下必须紧接
LoadLibrary调FormatMessage+GetLastError(),不能只打印数字:DWORD err = GetLastError();没用,得转成可读字符串 - 别在日志函数里封装错误打印逻辑:日志本身可能触发系统调用,导致错误被覆盖
路径和文件名不能自动补全,必须显式拼对
LoadLibrary("foo") 会自动尝试 foo.dll,但 dlopen("foo") 不会加前缀或后缀,也不会找 libfoo.so —— 它就去找字面量为 "foo" 的文件,大概率失败。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- Linux 下传入路径必须带完整文件名和扩展名:
"./libplugin.so"或"libplugin.so"(依赖LD_LIBRARY_PATH) - Windows 下推荐用绝对路径或当前目录相对路径:
R"(.\plugin.dll)";避免只传"plugin",因为搜索顺序里“可执行文件所在目录”是倒数第二位,容易加载错版本 - 路径分隔符用
/即可,Windows API 支持正斜杠;不要用std::filesystem::path拼接后调.string().c_str(),Windows 下宽字符路径(L"...")和多字节路径行为不一致
符号查找失败,90% 是 C++ name mangling 搞的鬼
dlsym(handle, "init") 和 GetProcAddress(h, "init") 都找不到 C++ 成员函数、模板或普通 int init() —— 因为编译器把名字改成了类似 _Z4initv 或 ?init@@YAHXZ 这样的玩意儿。
- 导出函数必须用
extern "C"包裹,且 Windows 还要加__declspec(dllexport),Linux 加-fPIC -shared - 类不能直接导出;要用工厂函数:
extern "C" Plugin* create_plugin();,然后在插件内部 new 实例 - 调试时别猜符号名:Linux 用
nm -D libxxx.so或objdump -T,Windows 用dumpbin /exports xxx.dll
卸载逻辑必须按平台分别实现,std::shared_ptr 删除器不能共用
同一个删除器函数,传给 std::shared_ptr<void></void> 管理 dlopen 和 LoadLibrary 句柄,迟早崩。因为 dlclose 对空指针或已关闭句柄返回 0(安全),而 FreeLibrary 对无效 HMODULE 直接触发访问违规。
- Linux 删除器里只需判断
handle != nullptr,然后无条件调dlclose(handle) - Windows 删除器里必须先验证句柄有效性:
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, name, &h),再调FreeLibrary;否则热重载时极易 double-free - 别用
std::unique_ptr加默认删除器——它默认调delete,你得手动传删除器,反而更容易漏写平台分支
最常被忽略的其实是依赖加载时机:Linux dlopen(RTLD_LAZY) 只在首次调用符号时才解析依赖,Windows LoadLibrary 会立即递归加载所有 DLL。这意味着同一套插件,在 Linux 上能跑几分钟才崩,在 Windows 上启动就报 ERROR_MOD_NOT_FOUND —— 不是代码问题,是路径配置没对齐。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










