Linux gcc 链接问题

cho*_*ppe 1 c c++

我有两个名为 ( lib1 和 lib2) 的库,它们都不相互依赖。我无法控制这些库的构建方式。当我尝试链接它们时,链接顺序决定了最终可执行文件中的不同行为,

例如:

如果我将它们链接为 [1]

gcc $(CC_FLAGS) -o app.out -llib1 -llib2 
Run Code Online (Sandbox Code Playgroud)

一切正常

但是,如果我将它们链接如下 [2]

gcc $(CC_FLAGS) -o app.out -llib2 -llib1 
Run Code Online (Sandbox Code Playgroud)

在可执行文件运行期间发生分段错误。

有关此问题原因的任何建议或指示都会有所帮助。

更新:

这两个库都依赖于另一个动态库,即 Apache Thrift(版本 0.11.0),如果编译上述 [1] 选项,则在 lib1 上发生段错误,如果使用上述选项 [2] 编译,则在 lib2 上发生异常.

更新 2

该问题是由于库之间的全局命名空间冲突造成的。由于 thrift 使用 IDL 机制来生成源文件,两个库(不知何故)为其 IDL 定义定义了相同的命名空间,因此观察到了这种行为。接受以下答案为正确答案,因为它间接解决了问题。

谢谢你。

hid*_*pha 6

这两个库中是否有可能存在一个符号(同名)?

链接器将使用哪一个来解析此类符号的使用取决于顺序(不确定我在哪里阅读过)。

(提示:这只是一个猜测)

所以让我们假设 lib1 定义了这个函数:

void foo( int, char* );
Run Code Online (Sandbox Code Playgroud)

而 lib2 定义了:

void foo( int );
Run Code Online (Sandbox Code Playgroud)

在某个地方,我们有一个类似的电话:

foo( 42 );
Run Code Online (Sandbox Code Playgroud)

现在如果链接器找到 lib1 的定义,这个 foo 很可能会得到有趣的垃圾作为它的第二个参数。

更新(对问题更新的反应)

以我们所拥有的洞察力,很难做出准确的陈述。所以我只能指出一些猜测,希望它们能帮助你。很抱歉我在这里的不准确。但我不知道我还能如何继续:

猜一猜

更新说:“如果使用上面的 [1] 选项编译 lib1,则会发生段错误,如果使用选项 [2] 编译,则会在 lib2 上发生异常

lib1 中的 ABI 不兼容异常处理?像这样的东西?

猜猜2(或者我应该将其命名为“故事”):

我们的代码继承(并实现)了一个在 thrift 头文件中声明的抽象类。这个 impl 然后被传递到 lib1/lib2(通过我们的冲突符号),它执行对这个 impl 的调用。但是 lib1 在编译期间使用了不同的 thrift 头文件(或者使用了条件编译,或者使用了其他版本的 thrift)。

  • @NateEldredge *两个库都被拉入,链接应该失败,并出现有关多个定义的错误。*不适用于共享库,链接器在按顺序检查库时只会注意到该符号存在。如果您对生成的可执行文件执行“ldd ...”,您将看到共享对象的加载顺序。通常,加载与“wins”匹配的符号的第一个库。并且匹配**仅**通过符号名称,因此 `foo( int )` 将匹配 `foo( char * )` 甚至 `foo( uint64_t *array )`。 (2认同)