You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何仍有进程使用共享库时会触发其卸载析构函数?

核心结论

你对共享库加载卸载机制的理解存在偏差,不存在“共享库要等所有使用它的进程全部退出才会卸载、执行析构函数”的全局规则。你混淆了共享库的物理内存共享特性,和进程维度独立的库生命周期逻辑。

共享库的实际运行逻辑

  • 所谓“共享”仅作用于物理内存层:共享库的只读段(代码、只读常量等)在物理内存中只会存储一份,内核通过页表把这块物理内存映射到不同进程的虚拟地址空间,达到节省物理内存的目的,这就是“共享库”名称的来源。
  • 库的构造、析构、加载、卸载都是进程私有行为:每个进程拥有完全独立的虚拟地址空间,进程启动时动态链接器(ld.so)会单独给当前进程做共享库的地址映射,执行库的constructor构造函数,同时在当前进程的内存结构里维护该库的引用计数。当进程退出,或是进程内调用dlclose把库的引用计数降到0时,动态链接器就会给当前进程持有的这个库实例执行destructor析构函数,撤销当前进程对该库的地址映射。整个流程完全不关心其他进程有没有在使用同一个库文件,也不会对其他进程造成任何影响。
  • 你之前认知里的“等所有使用者释放才卸载”的规则,只在单个进程内部生效:如果同一个进程里多次调用dlopen加载同一个共享库,动态链接器会累加该库在本进程内的引用计数,只有所有对应的dlclose调用完成、引用计数归0时,才会在这个进程里执行析构、卸载映射。跨进程场景下不存在全局统一的库引用计数,不同进程的库生命周期完全独立、互不干扰。

对你实验现象的解释

你观测到的输出完全符合正常机制:

  1. 第一个启动的main_while_sleep进程,动态链接器为它映射libdemo.so时执行构造函数,打印Loading....;进程运行的10秒内一直持有该库的映射,等循环结束进程退出前,执行析构函数打印Unloading...。
  2. 之后启动的main是和前者完全隔离的独立进程,动态链接器会为这个新进程单独映射一份libdemo.so的虚拟地址空间,再次执行构造函数打印Loading....;等main的逻辑执行完成退出时,自然会为这个进程自己持有的库映射执行析构,打印Unloading...。这个操作根本不会碰还在运行的main_while_sleep的内存空间——后者的库映射始终有效,等它自己退出的时候还是会正常跑析构,和你看到的两边输出完全对应。

内容的提问来源于stack exchange,提问作者Rick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:42:15