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

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

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

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

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

求问有没有大佬遇到过类似的情况,要被搞疯了。。。
1202 次点击
所在节点    C++
11 条回复
yanqiyu
3 天前
我觉得最简单的办法是在你的动态库里面加一个构造和析构会打 log 的对象看看这东西被析构了吗,如果不是的话去 gdb 给 dlopen 打断点看看是不是有别的没注意到的地方 dlopen 了

另外确定你们的环境不是 musl ?这东西的 dlclose 我记得是假的
yanqiyu
3 天前
@yanqiyu 哦,断点已经用过了,那要不看看能不能把 glibc 记录 refcount 的结构抓出来看看?
ysc3839
3 天前
还是提供初始化和卸载函数吧
seers
3 天前
dlclose 后检查下 soinfo 链,看看是不是确实关闭了
Noicdi
3 天前
> 可以定义一个或多个在共享库被加载和卸载时自动执行的函数,这样在使用共享库时就能够完成一些初始化和终止工作了。不管库是自动被加载还是使用 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
3 天前
Ainokiseki
3 天前
@ysc3839 唉,我们代码有若干个全局 static 变量,一个个清太蛋疼了

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

@Noicdi 感谢,我周一试试 open 的时候带上 LOCAL 以及编译的时候加上那个 flag
passive
3 天前
计数器只是一个原因
dlclose 并不会卸载 so ,前两天 hackernews 上刚有讨论
iceheart
2 天前
dlclose 之后 cat /proc/[pid]/maps 确认有没有卸载。
Noicdi
19 小时 46 分钟前
所以那个链接里提到的内容是有用的?那我也细看一下,对你提出的问题还挺感兴趣的。

话说是 RTLD_LOCAL 还是 RTLF_LOCAL ?
hwdq0012
18 小时 40 分钟前
我的动态库加载和卸载都是基于我自己定义的接口, 安装时 ioc 注册, 卸载时 ioc 手动清除, 上周也遇到个程序退出后静态资源没析构导致进程没退出的问题, 把那静态变量放 ioc 容器里就解决了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1157377

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX