破坏两个共享对象之间 common 类 内的静态成员?

Destruction of static members inside common classes between two shared objects?

我有以下层次结构:

  1. 类 具有多个静态 std::map,在 cpp 中初始化如下
 std::map<int, string> ClassA::MyStaticMap = ClassA::InitializeMyStaticMap()
  1. 包含这些 类.
  2. 的共享对象 libfoo.so
  3. 包含这些 类.
  4. 的共享对象 libbar.so
  5. 利用这两个库的应用程序。

我在应用程序中这些地图的析构函数中崩溃了。默认情况下符号是可见的,我没有更改可见性设置。

当我使用 g++ 的 -s 选项从 so 中删除符号时,崩溃消失了。

我对如何解决这个问题有一个设想,不确定哪个更好:

  1. 继续剥离符号 table,(不确定是否有更多我应该注意的含义)。
  2. 将这些共同的东西移动到第 3 个共享对象中,并使 libfoo.solibbar.so 动态地 link 反对。

哪个更好?还有为什么会发生崩溃,我试图了解发生了什么但我做不到。


编辑 1

GCC 版本:4.3.3

目标平台:Linux - RH 7.5

简短回答:不要依赖从 DSO 导出的代码中的全局变量。

// from lib foo
class B {
public:
  B(std::map<int, string>& map)
    : a_map_ref(map) {}

  std::map<int, string>& a_map_ref;
};

// from lib bar
class C {
public:
  C(std::map<int, string>& map)
    : a_map_ref(map) {}

  std::map<int, string>& a_map_ref;
};

// in your exe

int main() {

  // Here's my map. I know where it is. I can manage its lifetime
  std::map<int, string> a_map;

  // now I don't care about libFoo initialisation
  {
    loadLibFooDSO();
    {
      B* b = new B(a_map);

      // do thing 
 
      delete b;
    }
    unloadLibFooDSO();
  }

  // now I don't care about libBar initialisation
  {
    loadLibBarDSO();
    {
      C* c = new C(a_map);

      // do thing

 
      delete c;
    }
    unloadLibBarDSO();
  }

  // because my map will correctly be cleaned up on exit
 
  return 0;
}

长答案,有很多原因可能导致此问题。您没有提供有关 ClassA::MyStaticMap 如何链接到程序中的任何信息,因此或多或少是不可能说的。

如果它在静态库中,那么 libfoo 和 libbar 都会有自己的 ClassA::MyStaticMap 副本。无论哪个库首先加载,最终都将拥有 ClassA::MyStaticMap 的实例(另一个将简单地使用现有符号)。因此,如果首先加载 libfoo,则 libber 将使用 libfoo 版本的变量。如果 libfoo 先被销毁,libbar 将尝试销毁一个已经被销毁的变量。

简单的解决方案是:不要从 DSO 全局导出数据。仅将 DSO 接口保留为函数,您通常就可以了(ish,有一些注意事项)。

还有其他可能导致崩溃的原因,请选择以下任一原因:

  1. 一个 DSO 是在启用调试的情况下构建的,另一个是发布构建。
  2. 一个 DSO 使用 C++98 构建,另一个使用 C++17。
  3. 一个 DSO 是用 VC++ 构建的,另一个是 clang。