动态库

时间:2017-06-27 14:58:38

标签: c++ linux c++11 gcc

要理解问题,我应该告诉你更多关于加载动态库的程序。它是Half-Life Dedicated服务器。它使用旧的libstdc ++,它位于可执行文件旁边。 为了避免问题,当使用新标准库中的功能时,我通常会将我的项目staticaly链接到libstdc ++。

我的朋友告诉我,libstdc ++静态链接可能会产生问题,如果加载了不同的编译器库,或者我从服务器调用函数(在内部用旧的libstdc ++实现)。

这是真的吗?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

您的共享库公开的API必须使用与主机应用程序所期望的相同的ABI,即所涉及的类型必须具有相同的布局,大小和对齐方式。

如果API中暴露了std::个类型或者它抛出了C ++异常,那么这意味着必须使用定义的相同标准库头和宏来编译共享库。在这种情况下,您可以动态链接到主机应用程序附带的libstdc++

如果API中没有公开std::类型,并且共享库中没有引发异常,则可以静态链接到libstdc++。但是,所有外部符号仍将从共享库中公开,因此当加载调用dlopen而没有RTLD_DEEPBIND标志时,它将使用来自同一名称的符号。主机应用程序,如果它们可用而不是您希望静态链接的应用程序,这可能会导致您的朋友可能引用的未定义行为。为避免这种情况,需要使用链接器版本脚本来使共享库中的所有符号都是本地的,并且只将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链接器选项。

另外,请仔细阅读

了解更多详情。

答案 1 :(得分:0)

是的,这是真的。最简单的示例是,如果您在库中创建一个new的对象,而在另一个不使用相同STL的库中delete创建一个对象。

你有2个解决方案:

  • 为STL使用动态链接
  • 确保不兼容性不跨越二进制文件(library,exe)的边界。很难做到这一点的方法是让你的库只公开一个C API(没有C ++)。
相关问题