我有两个名为 ( 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 定义定义了相同的命名空间,因此观察到了这种行为。接受以下答案为正确答案,因为它间接解决了问题。
谢谢你。
这两个库中是否有可能存在一个符号(同名)?
链接器将使用哪一个来解析此类符号的使用取决于顺序(不确定我在哪里阅读过)。
(提示:这只是一个猜测)
所以让我们假设 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)。