c – 依赖地狱:linux .so插件动态加载
作者:互联网
我使用linuxbrew创建了一个使用独立构建树构建的共享库,由于依赖性冲突,它无法加载到父应用程序中.我正在使用一个单独的应用程序,它在启动后使用Qt5 QLibrary类动态加载库.
我的库是libv_repExtPluginSkeleton.so.它和父应用程序都依赖于glibc和libstdc.所有主应用程序的依赖项都在/usr/lib中,而我所有库的依赖项都在〜/ .linuxbrew / lib中.
当父应用程序加载.so失败时,我使用LD_DEBUG = all“$dirname / $appname”调试失败,并在输出中找到以下错误报告:
2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]; dynamically loaded by libQt5Core.so.5 [0]
2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]; generating link map
2610: dynamic: 0x00007fd063cff570 base: 0x00007fd063ae7000 size: 0x000000000021a6a8
2610: entry: 0x00007fd063af1150 phdr: 0x00007fd063ae7040 phnum: 5
2610:
2610: checking for version `GCC_3.0' in file /lib/x86_64-linux-gnu/libgcc_s.so.1 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBC_2.14' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `CXXABI_1.3' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBCXX_3.4.9' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBCXX_3.4.21' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: error: version lookup error: version `GLIBCXX_3.4.21' not found (required by /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so) (fatal)
2610:
2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]; destroying link map
正如您所看到的,当我的库加载时,似乎已加载的glibc版本在/usr/lib中,但我的库需要在〜/ .linuxbrew / lib中加载版本.
QLibrary用于加载插件,如下所示:
plug=new CPlugin(filename,pluginName);
int loadRes=plug->load();
我在The Inside Story on Shared Libraries and Dynamic Loading中读到“动态加载的模块与底层应用程序完全分离”,如果可以使其正常工作,我想重新配置加载过程来解决问题.
以下是ldd找到的依赖项列表,它说明了不同位置的依赖项重叠:
+ ldd /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so
linux-vdso.so.1 (0x00007fffc17af000)
libstdc++.so.6 => /home/hbr/.linuxbrew/lib/libstdc++.so.6 (0x00007ff5b9a32000)
libm.so.6 => /home/hbr/.linuxbrew/lib/libm.so.6 (0x00007ff5b9742000)
libgcc_s.so.1 => /home/hbr/.linuxbrew/lib/libgcc_s.so.1 (0x00007ff5b9531000)
libc.so.6 => /home/hbr/.linuxbrew/lib/libc.so.6 (0x00007ff5b91b9000)
/home/hbr/.linuxbrew/Cellar/glibc/2.19/lib64/ld-linux-x86-64.so.2 (0x00007ff5b9f81000)
+ ldd /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/vrep
linux-vdso.so.1 => (0x00007ffc333f9000)
liblua5.1.so (0x00007fc10e763000)
libQt5Core.so.5 (0x00007fc10df28000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc10dd0a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc10da 2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]; dynamically loaded by libQt5Core.so.5 [0]
2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]; generating link map
2610: dynamic: 0x00007fd063cff570 base: 0x00007fd063ae7000 size: 0x000000000021a6a8
2610: entry: 0x00007fd063af1150 phdr: 0x00007fd063ae7040 phnum: 5
2610:
2610: checking for version `GCC_3.0' in file /lib/x86_64-linux-gnu/libgcc_s.so.1 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBC_2.14' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `CXXABI_1.3' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBCXX_3.4.9' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: checking for version `GLIBCXX_3.4.21' in file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] required by file /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]
2610: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: error: version lookup error: version `GLIBCXX_3.4.21' not found (required by /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so) (fatal)
2610:
2610: file=/home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/libv_repExtPluginSkeleton.so [0]; destroying link map
)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc10d7f0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc10d42b000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc10d125000)
libicui18n.so.54 (0x00007fc10ccb7000)
libicuuc.so.54 (0x00007fc10c909000)
libicudata.so.54 (0x00007fc10aedf000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc10acdb000)
libgthread-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0 (0x00007fc10aad9000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc10a8d1000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007fc10a5c9000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc10e66d000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fc10a38b000)
+ LD_DEBUG=all /home/hbr/V-REP_PRO_EDU_V3_2_2_64_Linux/vrep
解决方法:
How can I resolve this version conflict so that my library loads correctly?
这对libc或libstdc等基本的低级库不起作用.这些库管理全局对象的数量(内存管理,线程,环境,语言环境等),并且在同一地址空间中具有多个不同版本的库是灾难的处方.更重要的是,不保证不同libstdc版本的STL类在内存中具有相同的二进制布局.应用程序内的std :: string可能与库中的std :: string不同.从/向插件传递一个可能会导致难以调试的崩溃. (你为libstdc获得的错误消息部分是对这种情况的保护.)这导致了一个问题(即使你静态链接libstdc)你的插件的功能将无法接受或返回STL类作为参数/返回值 – 只有基本的C类型.
此外,通过动态加载,另一个障碍是Linux / UNIX链接器使用具有其符号的扁平线性列表的扁平线性列表库.并且库由内部soname标识,而不是文件名.链接器将所寻找的符号绑定到第一个,通过线性搜索通过库列表及其符号找到.稍后加载的库将从已经为应用程序本身加载的库中获得大部分符号.您的插件引用的库可能甚至都没有被查看.
总的来说,您的选择非常有限:
>静态链接.将插件与所需库的静态变体相链接.但是,如果您需要覆盖libc或libstdc,那么这不起作用.
>服务器/客户端方法.插件库是一个瘦包装器,只启动服务器进程,然后通过某种RPC机制将所有从应用程序到插件的调用重定向到此服务器应用程序.这是解决库版本冲突的唯一可靠方法.由于与库不同,应用程序可以更好地控制动态链接器(rpath,或者在最坏的情况下使用LD_PRELOAD).
通常,正如其他人之前所说的那样,您应该始终使用随操作系统安装的libc和libstdc,并根据需要为不同的OS变体发布不同的版本.
标签:c-2,linux,dependencies,shared-libraries,dynamic-loading 来源: https://codeday.me/bug/20190623/1271751.html