如果我在 Linux 上更改 C++ 动态共享库而我的可执行程序在它上面使用会发生啥

Posted

技术标签:

【中文标题】如果我在 Linux 上更改 C++ 动态共享库而我的可执行程序在它上面使用会发生啥【英文标题】:what would happened if I changed the C++ Dynamic Shared Library on Linux while my executable program using on it如果我在 Linux 上更改 C++ 动态共享库而我的可执行程序在它上面使用会发生什么 【发布时间】:2020-01-20 03:02:37 【问题描述】:

我在Linux上有一个C++动态共享库abc.so,我的可执行程序用dlopen动态加载它,然后用rm + cp覆盖abc.so的新版本,以防使用@的inode发生变化987654327@,但有时也有coredump,我意识到这可能与动态共享库的延迟加载有关,但我无法确认,任何人都可以帮我弄清楚为什么?非常感谢!

【问题讨论】:

POSIX 系统(如 Linux)不会真正覆盖某些应用程序打开的文件。而是在磁盘上创建一个新文件,随后的打开调用将找到该文件。旧文件仍然存在,直到最后一个引用该文件的应用程序“关闭”它。 在重新启动程序之前可能什么都没有。 Ubuntu 现在正在提供内核热补丁以避免机器重新启动,但我不知道热补丁正在应用于用户空间。另请参阅 Ubuntu wiki 上的 Kernel Livepatch。微软多年来一直为内核和用户库提供热补丁。另请参阅Microsoft Detours 库。 【参考方案1】:

没有自己调查的可能性,这变成了推测,但使用:

rm abc.so
cp new_version.so abc.so

对已经加载 abc.so 的程序没有影响。对于与abc.so 链接的程序(或使用dlopen 加载它),如果在删除文件或将其复制到位时启动它们(或使用dlopen),则会出现问题。结果很可能是核心转储。

替换abc.so的更好方法:

copy new_version.so to the same filesystem as abc.so (like the same directory)
mv new_version.so abc.so

这可确保在预期的位置始终存在abc.so 的完整版本。任何需要它的程序都将获得旧版本新版本 - 两者之间没有任何内容。

【讨论】:

感谢您的回复。我发现当我的可执行程序使用 RTLD_LAZY dlopen abc.so 时,如果我将 abc.so 替换为 new_version.so(甚至使用 mv),结果会变得推测性,尤其是 abc.so 的 ABI 已更改 @W.Terry 我很惊讶RTLD_LAZY 对此有任何影响。如果你启动你的程序,让它dlopen(RTLD_LAZY...) 然后删除abc.so 而不替换它呢?解析符号时会崩溃吗?如果您更改了界面,您需要使用abc.so 重新编译应用程序,所以我希望您只是作为测试这样做? 感谢@Ted Lyngmo,我重新测试了所有案例,结果证明你的结论是对的。

以上是关于如果我在 Linux 上更改 C++ 动态共享库而我的可执行程序在它上面使用会发生啥的主要内容,如果未能解决你的问题,请参考以下文章

GitHub - 如何在共享服务器上克隆存储库而不授予我所有存储库的访问权限

Linux 共享库

Linux:作为共享对象 API 的 C++ 抽象类

C++学习(二五零)动态库和静态库的选择顺序

Linux-Ubuntu:具有动态分配变量的共享内存,必须由其他可执行文件更改

C++ 静态库中的共享全局变量:Linux