为了理解问题,我应该告诉你更多关于加载动态库的程序。这是半条命专用服务器。它使用位于可执行文件旁边的旧 libstdc++。 为避免出现问题,在使用新标准库中的功能时,我通常将我的项目静态链接到 libstdc++。
我的 friend 告诉我 libstdc++ 静态链接会产生问题,如果加载了 2 个使用不同编译器库编译的库,或者当我从服务器调用函数时(这是根据旧 libstdc++++ 内部实现的)。
这是真的吗?我该如何解决这个问题?
最佳答案
您的共享库公开的 API 必须使用与主机应用程序期望的相同的 ABI,即涉及的类型必须具有相同的布局、大小和对齐方式。
如果有std::
API 中公开的类型或抛出 C++ 异常,则这意味着必须使用相同的标准库头文件和定义的宏来编译共享库。在这种情况下,您可以动态链接到那个 libstdc++
随主机应用程序一起提供。
如果没有std::
API 中公开的类型并且共享库中没有抛出异常,您可以静态链接到 libstdc++
.然而,所有外部符号仍然会从共享库中暴露出来,因此当调用 dlopen
加载它时。没有RTLD_DEEPBIND
标志,它将使用主机应用程序中具有相同名称的符号(如果它们可用)而不是您希望静态链接的符号,这可能会导致您的 friend 可能提到的未定义行为。为避免这种情况,需要链接器版本脚本将共享库中的所有符号设为本地,并且仅将 API 符号公开为全局。像这样的东西:
MYHALFLIFEPLUGIN_0.0 {
global: half_life_foo,half_life_bar; # Explicitly list symbols to be exported.
local: *; # Hide everything else.
};
并指示链接器将此脚本与-Wl,--version-script=<filename>
一起使用编译器链接器选项 ( LDFLAGS
)。除了-static-libstdc++
选项,您将需要 -static-libgcc
链接器选项。
另外,仔细阅读
了解更多详情。
关于c++ - 动态库中的 libstdc++ 静态链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44783614/