链接到不进行函数调用的库有什么影响?

我有一个程序的make文件,链接到libdl.so与以下行-ldl。 没有调用dlopen或任何相关函数。 即使您不使用任何function,以这种方式链接到此库有什么影响?

您必须阅读链接器的文档。 来自我的Linux / ELF / GNU Binutils系统上的info ld (强调添加):

 `--as急需”
 `--no-按需”
     此选项会影响动态库的ELF DT_NEEDED标记
     在`--as-needed'选项后的命令行中提到。
      通常,链接器将为每个动态添加DT_NEEDED标记 
       在命令行中提到的库,无论是否 
       实际上是否需要库。  `--as-needed'导致a
      DT_NEEDED标记仅为满足a的库发出
     来自常规对象文件的未定义符号引用,或者,如果是
     在其他库的DT_NEEDED列表中找不到库
     链接到那一点,来自的未定义的符号引用
     另一个动态库。  `--no-as-needed'恢复默认值
     行为。

您可以通过在测试程序上运行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 -Wl,--as-neededlibdl将不会被链接。根据我的测试,这只适用于-Wl,--as-needed -ldl 之前的命令行中列出。

有什么影响? 这意味着即使您不使用共享库,您的二进制文件也不会在没有共享库的系统上运行。 这也意味着如果升级共享库并卸载旧库,则二进制文件将中断。 这不是什么大问题,因为二进制兼容性无论如何都是一个熊,但我认为没有理由不开启-Wl,--as-needed一般来说是项目-Wl,--as-needed

我编写了一个只使用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的function。 但是,无论如何都会添加boost_thread作为我的应用程序的依赖项(正如您在ldd的输出中看到的那样)。

链接到共享库与链接静态库不同。 主要的差异已由@Dietrich Epp解释,但还有另一个重要细节。 共享库定义函数void _init()void _fini(void) ,这些函数在加载/卸载共享库时调用; 如果您不自己定义它们,链接器将添加默认存根。

如果您将程序链接到共享库,但是不引用库中的任何符号(并且不添加–as-needed链接器标志),也会调用这些。

大多数链接器将简单地省略最终二进制文件中未使用的对象,就像您首先没有链接到库一样。