我有一个程序的make文件,链接到libdl.so,并带有以下行-ldl。没有调用dlopen或任何相关函数。即使您不使用任何函数,以这种方式链接到此库会有什么影响?
答案 0 :(得分:4)
您必须阅读链接器的文档。来自我的Linux / ELF / GNU Binutils系统上的info ld
(强调添加):
`--as-needed' `--no-as-needed' This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the `--as-needed' option. Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not. `--as-needed' causes a DT_NEEDED tag to only be emitted for a library that satisfies an undefined symbol reference from a regular object file or, if the library is not found in the DT_NEEDED lists of other libraries linked up to that point, an undefined symbol reference from another dynamic library. `--no-as-needed' restores the default behaviour.
您可以通过在测试程序上运行ldd
来检查自己。在一个简单的测试程序中,我得到:
linux-vdso.so.1 => (0x00007fffd8305000)
libc.so.6 => /lib/libc.so.6 (0x00007f646c669000)
/lib/ld-linux-x86-64.so.2 (0x00007f646c9ca000)
但是,如果我与-ldl
相关联,我就明白了:
linux-vdso.so.1 => (0x00007fff644f1000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fb9b1375000)
libc.so.6 => /lib/libc.so.6 (0x00007fb9b1014000)
/lib/ld-linux-x86-64.so.2 (0x00007fb9b1579000)
即使我的程序没有使用libdl
。但是,如果我使用-Wl,--as-needed
运行GCC,则libdl
将不会被链接。根据我的测试,只有在命令行之前列出-Wl,--as-needed
时才能使用此功能 -ldl
。
有什么影响?这意味着即使您不使用共享库,您的二进制文件也不会在没有共享库的系统上运行。这也意味着如果升级共享库并卸载旧库,则二进制文件将中断。这不是什么大问题,因为无论如何二进制兼容性都是一个熊,但我认为没有理由不为项目开启-Wl,--as-needed
。
答案 1 :(得分:1)
我编写了一个只使用STL的小应用程序。它的大小 8275字节,无需链接到任何特定库:
linux-gate.so.1 => (0x00e1e000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x0015a000)
libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x0044b000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00741000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00250000)
/lib/ld-linux.so.2 (0x00a75000)
现在,当我编译它并将其与boost_thread链接时,它会增长到 8290字节:
linux-gate.so.1 => (0x009d9000)
libboost_thread.so.1.40.0 => /usr/lib/libboost_thread.so.1.40.0 (0x00e59000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x003a3000)
libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00bc5000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00f8a000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00110000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x00bf0000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x00dd8000)
/lib/ld-linux.so.2 (0x00ba3000)
请注意,我的代码上没有函数调用boost_thread的功能。但是,无论如何都会添加boost_thread作为我的应用程序的依赖项(正如您在 ldd 的输出中看到的那样)。
答案 2 :(得分:1)
链接到共享库与链接静态库不同。主要的差异已由@Dietrich Epp解释,但还有另一个重要细节。共享库定义了在加载/卸载共享库时调用的函数void _init()
和void _fini(void)
;如果你自己没有定义它们,链接器将添加默认存根。
如果您将程序与共享库链接,但也不会引用库中的任何符号(并且不添加--as-needed链接器标志),那么也会调用它们。
答案 3 :(得分:0)
大多数链接器将简单地省略最终二进制文件中未使用的对象,就像您首先没有与库链接一样。