G ++动态库链接问题

时间:2014-03-13 16:18:28

标签: c++ g++ dynamic-linking

我试图将许多动态库链接到一个应用程序中并遇到g ++的问题。

考虑:

  • libA.so
  • libB.so依赖于libA.so
  • libC.so依赖于libB.so
  • 应用程序D直接依赖于libC.so

如果我尝试将应用程序D链接到libC.so,我会得到A和B中符号的未解析符号。我觉得好像编译器应该能够解决它,当我使用intel编译器时,它确实。但是,G ++无法弄清楚链接。我希望我的库和可执行文件只需链接到他们直接需要的东西,而不是试图预测他们使用的库需要什么。

当libA.so链接到静态库时,我也遇到了问题,当我尝试编译可执行文件时,我会从libA.so应该使用的静态库中获取未解析的符号。

我已经看到其他一些人问这个和类似的问题并得到各种答案(Linking with dynamic library with dependencies),但答案都很模糊,经常相互冲突,而且非常符合“保持”关于货运和RTFM“。

我觉得链接顺序很重要。怎么样,我怎么知道要链接的顺序呢?

更新

我相信正在发生的事情是libA.so包含两个函数(AA和AB)。 libB.so需要AA和libC.so需要AB。当libB.so被链接时,g ++获得libA.so,看到只使用AA,并丢弃AB。然后当链接到libC.so时,g ++看到libA.so已经链接并且没有重新访问它,导致AB未定义。我已经看到文档表明静态库以这种方式工作,但编译器是否会以相同的方式处理动态库?如果是这样,有办法解决它吗?

2 个答案:

答案 0 :(得分:2)

(你没有显示实际的链接器错误,或者提供了足够的关于问题的信息,所以接下来是部分猜测......)

  

如果我尝试将应用程序D链接到libC.so,我会得到A和B中符号的未解析符号。

链接可执行文件时,GNU链接器会检查所有符号是否可用。您可以使用--allow-shlib-undefined将其关闭(告诉GCC将其传递给链接器使用-Wl,--allow-shlib-undefined

最好不要使用该选项,但在这种情况下,链接器需要知道在哪里找到libA.solibB.so,以便它可以检查libC.so所需的符号是否会被发现。您可以使用-rpath-link链接器选项

来实现
  

使用ELF或SunOS时,一个共享库可能需要另一个共享库。当“ld -shared”链接包含共享库作为输入文件之一时,会发生这种情况。

     

当链接器在执行非共享,不可重定位链接时遇到这种依赖关系时,它将自动尝试找到所需的共享库并将其包含在链接中(如果不包含在内)明确地

因此,您应该能够通过使用-Wl,-rpath-link,.告诉链接器查找库.所依赖的当前目录(libC.so)来解决问题。

  

我觉得链接顺序很重要。怎么样,我怎么知道要链接的顺序呢?

是的,链接顺序很重要。你应该以明显的顺序链接;-)如果一个文件foo.cc依赖于一个库,那么稍后将该库放在链接器行中,这样就可以在处理后找到 {{1}如果该库依赖于另一个库甚至更晚,那么它将在需要它的早期库之后处理。如果您在链接行的开头放置一个库,那么链接器没有任何未解析的符号可以查找,因此不需要链接到该库。

答案 1 :(得分:0)

您需要明确指定直接使用的所有库。

在静态链接期间,不使用加载的.so的依赖项;链接主程序时,必须在主程序本身,命令行中指定的静态库或命令行中指定的共享库中找到所有符号。

这是您收到错误的地方。

执行程序时,会加载动态库的依赖关系,以便可以解析其他共享库中的引用。 当程序运行时,它实际上可能(动态地)链接到不同版本的共享库。这个不同的版本可能有不同的依赖关系,因此主程序必须依赖于作为依赖项加载的其他库集。

这就是静态链接器提前阻止你的原因。