一个库(.so)可以动态加载另一个用不同编译器构建的库吗

Can a library (.so) dynamically load another library built with a different compiler

总结:

我在一个库动态加载另一个库时遇到问题,我想知道编译器的差异是否是根本原因。

问题详情:

我的应用程序链接到 libgbm.so,动态加载 libpvrGBMWSEGL.so,然后请求 gbm_backend 函数。

#libgbm.so

module = dlopen("/usr/lib/libpvrGBMWSEGL.so", RTLD_NOW | RTLD_GLOBAL)
dlsym(module, entrypoint)

当我尝试使用提供的符号时,它抛出一个分段错误。

分析:

libpvrGBMWSEGL.so 作为专有二进制 blob 提供。快速分析表明它是使用 Linaro GCC 5.3-2016.02

构建的
> strings libpvrGBMWSEGL.so | grep GCC
GCC: (Linaro GCC 5.3-2016.02) 5.3.1 20160113

同时,动态调用它的库 libgbm 是使用 Buildroot GCC 6.4.0 构建的

> strings libgbm.so | grep GCC
GCC: (Buildroot 2017.11-git-00884-g7af8140-dirty) 6.4.0

问题:

我是否应该期望这两个库在我使用它们的方式上兼容?

对于许多平台,编译器都应遵守已发布的 ABI 文档。对于 C++ 和在这些平台 ABI 之上,有 Itanium C++ ABI(它与 Itanium 不再有任何关系,我认为它将是 Itanium 对计算的持久贡献)。

不过,这不会扩展到图书馆。 Linux 有许多 libcs​​,针对 glibc 编译和链接的东西不会 运行 在 Bionic libc (Android) 上,反之亦然,即使体系结构匹配。 C++ 标准库本质上也是如此(甚至 GCC 附带的实现也带有略微不同的 ABI 作为选项)。

对于 ARM,还有大量的子架构变化。

总结就是:当每个人都努力时,那么你努力做的事就会成功。如果没有,可能不会。在 C++ 中正确实现这一点比在 C 中更难。