共享库链接静态库与通用接口但实现不同

时间:2017-05-16 18:10:58

标签: c++ linux gcc shared-libraries ld

注意:请耐心等待,因为这是令人费解的。它也是为Windows设计的传统软件,我试图移植以兼容C ++标准/ Linux。我只会给出一些我能够重现问题的高级示例,因为我无法提供生产代码的示例。请不要问为什么我们这样做,只知道我们这样做,我必须处理它。

我们有许多共享库使用的静态库。例如,FirstSharedLib.so和SecondSharedLib.so都依赖于CommonStaticLibrary.lib。

现在,CommonStaticLibrary.lib声明了要由共享库实现的方法。例如,GetSharedLibraryName();

因此,FirstSharedLib项目通过返回“FirstSharedLib”为CommonStaticLibrary实现GetSharedLibraryName,同样SecondSharedLib通过返回“SecondSharedLib”来实现它。

这在Windows中可以正常工作,例如,当FirstSharedLib调用GetSharedLibraryName()时;它接收“FirstSharedLib”字符串,然后当SecondSharedLib调用GetSharedLibraryName()时;它接收“SecondSharedLib”字符串。

然而,在Linux(gcc / ld)中编译和运行时,动态链接器加载第一个共享库,看到CommonStaticLibrary :: GetSharedLibraryName()的实现,然后将其用于调用GetSharedLibraryName()的每个其他共享库,无论如何实际执行情况。

因此,在这种情况下,如果首先加载FirstSharedLib,则调用GetSharedLibraryName();它接收“FirstSharedLib”字符串,但是当加载SecondSharedLib时,它也会收到“FirstSharedLib”。

或者,如果首先加载SecondSharedLib,则对GetSharedLibraryName()的所有调用都将返回“SecondSharedLib”。

是否有一个链接器选项来预先链接静态库的共享命令,以便当SecondSharedLib调用GetSharedLibraryName()时,它总是调用该项目创建的实现?

请注意,当我们加载共享库时,我可以看到指向内存中唯一实现的指针,只要运行时总是在任何其他库调用它时调用第一个加载的实例化。

我们使用CMake作为我们的构建系统,但除了我将使用CMake命令传递链接器和/或编译器标志这一事实之外,这不应该太相关。

我尝试使用-fPIC来编译共享库,并将公共库方法的可见性设置为隐藏以试图限制其访问,但这两个选项都没有用。我们还试图修改Common库方法的一些签名,但是我们可以更改它的数量有限。

1 个答案:

答案 0 :(得分:1)

在我们加载动态库的方法中,我们传递了RTLD_GLOBAL,它显然覆盖了编译时传入的隐藏属性。

我们删除了RTLD_GLOBAL标志(替换为RTLD_LOCAL 0x0),现在这些库将静态库方法保留在发起共享库的本地。我们还能够删除标志以将属性设置为隐藏。

旧代码:

int flag = RTLD_NOW | RTLD_GLOBAL;
void* library = dlopen( libraryName, flag );

新代码:

int flag = RTLD_NOW | RTLD_LOCAL;
void* library = dlopen( libraryName, flag );