必须显式调用DLL/SO提供的shutdown()函数清理单例资源后再FreeLibrary/dlclose,否则易致资源泄漏、悬垂指针或崩溃;跨平台需extern "C"导出、原子标志防护及空指针检查。

Windows 下用 FreeLibrary 卸载 DLL 前必须先清理单例资源
直接调用 FreeLibrary 不等于安全卸载——如果 DLL 内部有单例对象持有线程、文件句柄或互斥量,FreeLibrary 返回后这些资源大概率已泄漏,甚至后续访问会触发崩溃。关键不是“能不能 unload”,而是“unload 时有没有人还在用”。
- 必须在调用
FreeLibrary之前,由宿主程序显式调用 DLL 提供的shutdown()函数(例如Config_shutdown()),该函数内部完成线程join()、句柄CloseHandle()、指针置空等操作 - MFC 程序必须用
AfxFreeLibrary替代FreeLibrary,否则可能破坏 MFC 全局状态,导致后续加载失败或内存异常 -
FreeLibrary成功返回只表示引用计数减一,不保证模块立即从内存卸载;若 DLL 被多次LoadLibrary,需对应次数的FreeLibrary才真正释放 - 禁止在
DllMain的DLL_PROCESS_DETACH分支中执行delete或调用虚函数,CRT 堆此时可能已不可用
Linux 下用 dlclose 卸载 SO 时 __attribute__((destructor)) 不可靠
dlclose 并不总是触发 __attribute__((destructor)) 函数,尤其当 SO 是直接链接进主程序(而非 dlopen 加载)时,该属性完全无效。依赖它做清理等于埋雷。
- 真正可控的方式是:宿主程序在调用
dlclose前,先用dlsym获取导出的 C 风格清理函数(如config_shutdown),并确保其被调用 -
__attribute__((destructor))函数内严禁使用std::string、std::cout、STL 容器析构等依赖 C++ 运行时堆的操作,否则极易触发std::terminate -
dlclose返回 0 表示成功减少引用计数,但模块是否真正卸载取决于符号是否仍在使用;若仍有函数指针指向 SO 内代码,模块不会释放 - SO 中所有全局对象(包括单例静态指针)的析构顺序不可控,不能在 destructor 函数中访问其他模块的静态变量
跨平台统一处理:显式 shutdown() + 原子标志 + 空指针检查
别指望系统自动帮你收尾。最稳妥的方案是把销毁逻辑完全暴露出来,由宿主程序控制时机,并用原子操作和空指针防御双重兜底。
- 单例类提供
static void shutdown(),内部用std::atomic<bool></bool>标记已销毁,首次调用才执行清理,避免重复 delete -
getInstance()开头必须检查该原子标志,若已 shutdown 则抛std::runtime_error("Singleton already destroyed"),而不是静默返回 nullptr - 导出函数必须是
extern "C",Windows 加__declspec(dllexport),Linux 加__attribute__((visibility("default"))),否则dlsym/GetProcAddress找不到符号 - 清理函数里禁止调用任何跨模块接口(比如日志库、网络库),只操作本模块内可确定存活的资源(如裸指针、POSIX 句柄、
pthread_mutex_t)
常见崩溃场景和对应规避点
很多段错误不是发生在 dlclose 当时,而是在之后某次误调用单例接口时才暴露——因为指针没清空,内存却已被回收。
- 现象:
Segmentation fault (core dumped)出现在getInstance()->doSomething(),但dlclose已成功返回 → 原因是单例指针未置空,getInstance()返回了悬垂指针 - 现象:主线程卡死在
std::mutex::lock()→ 原因是单例持有的std::mutex在dlclose后被析构,但锁对象内存已释放,再次 lock 触发未定义行为 - 现象:
dlclose后再dlopen同名 SO 失败,报Symbol not found→ 原因是旧 SO 的符号表残留,应确保每次加载前彻底卸载且无残留引用 - 现象:Windows 下
FreeLibrary返回 FALSE,GetLastError()为ERROR_INVALID_HANDLE→ 常见于传入了非法HMODULE,或该模块已被其他线程卸载
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











