V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Ainokiseki
V2EX  ›  C++

[求助] Linux 系统下动态库卸载后全局变量未重置的问题

  •  
  •   Ainokiseki · 7 小时 21 分钟前 · 390 次点击
    遇到一个头疼的问题,兄弟部门需要调用我的代码,我把代码封装成了.so 动态库给他们使用。他们会写很多测试 case ,每个 case 依次运行,运行时首先使用 dlopen 装载我的库,运行完毕后使用 dlclose 卸载。下一个 case 重新使用 dlopen 装载。

    目前遇到的问题是,在第二次 dlopen 之后,我的库里的全局变量的值仍然是上一次运行之后剩下的。而我期望在 dlclose 之后,全局变量们应该被析构掉,在 dlopen 之后重新构造以及初始化。

    我询问 AI 得到的信息是,dlclose 之后如果引用计数为 0 ,那么会进行我期望的析构过程。但是没有直接手段能查看引用计数。可能导致引用计数不为 0 的原因包括:多次 dlopen 只有一次 dlclose ;引用的其他动态库依赖了我的库。其中第一条我认为不可能,我通过断点和日志能确信只有一次 dlopen 和一次 dlclose 。第二条也不可能,我查看了所有动态库的依赖库,没有任何一个依赖我的库。

    我在 dlclose 和 dlopen 的时候均进行了检查,两次 dlopen 和一次 dlclose 都是成功的,没有错误信息。

    求问有没有大佬遇到过类似的情况,要被搞疯了。。。
    8 条回复    2025-09-06 00:43:45 +08:00
    yanqiyu
        1
    yanqiyu  
       7 小时 1 分钟前
    我觉得最简单的办法是在你的动态库里面加一个构造和析构会打 log 的对象看看这东西被析构了吗,如果不是的话去 gdb 给 dlopen 打断点看看是不是有别的没注意到的地方 dlopen 了

    另外确定你们的环境不是 musl ?这东西的 dlclose 我记得是假的
    yanqiyu
        2
    yanqiyu  
       6 小时 59 分钟前
    @yanqiyu 哦,断点已经用过了,那要不看看能不能把 glibc 记录 refcount 的结构抓出来看看?
    ysc3839
        3
    ysc3839  
       6 小时 27 分钟前 via Android
    还是提供初始化和卸载函数吧
    seers
        4
    seers  
       6 小时 18 分钟前 via Android
    dlclose 后检查下 soinfo 链,看看是不是确实关闭了
    Noicdi
        5
    Noicdi  
       3 小时 58 分钟前
    > 可以定义一个或多个在共享库被加载和卸载时自动执行的函数,这样在使用共享库时就能够完成一些初始化和终止工作了。不管库是自动被加载还是使用 dlopen 接口(参见 42.1 节)显式加载的,初始化函数和终止函数都会被执行。
    >
    > 《 Linux/Unix 系统编程手册》 42.2 初始化和终止函数

    那我的第一反应就是你提供全局变量的析构函数,注册到终止函数里,库被卸载的时候去析构。但是又考虑到库没被卸载。

    > Shared objects may export functions using the __attribute__((constructor)) and __attribute__((destructor)) function attributes. Constructor functions are executed before dlopen() returns, and destructor functions are executed before dlclose() returns. A shared object may export multiple constructors and destructors, and priorities can be associated with each function to determine the order in which they are executed. See the gcc info pages (under "Function attributes") for further information.
    >
    > man dlopen

    但是这里又说 `destructor functions are executed before dlclose() returns`,那试一试?
    Noicdi
        6
    Noicdi  
       3 小时 53 分钟前
    Ainokiseki
        7
    Ainokiseki  
    OP
       2 小时 1 分钟前 via Android
    @ysc3839 唉,我们代码有若干个全局 static 变量,一个个清太蛋疼了

    @seers 看过了,确实没有关闭。。不知道为啥

    @Noicdi 感谢,我周一试试 open 的时候带上 LOCAL 以及编译的时候加上那个 flag
    passive
        8
    passive  
       1 小时 8 分钟前 via Android
    计数器只是一个原因
    dlclose 并不会卸载 so ,前两天 hackernews 上刚有讨论
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1154 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 288ms · UTC 17:52 · PVG 01:52 · LAX 10:52 · JFK 13:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.