静态成员的两个实例,怎么可能?

Ezr*_*zra 6 c++ multithreading shared-libraries static-members

我有一个多线程的应用程序.我在共享库中声明了一个带有静态成员的类.

从不同库中的不同线程打印成员的地址会显示不同的结果.

//宣言

template <class OBJECT>
struct Container
{
   static int m_member;
};

template <class OBJECT>
int Container<OBJECT>::m_member;
Run Code Online (Sandbox Code Playgroud)

//打印

cout << (void*) &Container<int>::m_member << endl;
Run Code Online (Sandbox Code Playgroud)

怎么会这样?

rod*_*igo 6

如果你有不同的库,(我猜不同的动态库),那么你可能会有一些代码和静态变量的重复.

具体细节取决于您使用的特定动态库技术.我会说,例如,在Windows DLL中你会有重复的代码和变量,但在Linux SO中你不会.

无论如何,您应该提供有关操作系统和项目布局的更多详细信息.

更新:啊,但你的班级是一个模板!共享库中的模板实例化是一个奇怪的野兽!为了确保在所有进程中只使用了一个类的副本,您必须显式实例化模板,并确保在SO中导出此实例,并从客户端代码中使用它.详细信息因编译器而异,但您可以检查std::string完成的方式,例如:

在头文件中:

namespace std
{
    extern template class basic_string<wchar_t>;
}
Run Code Online (Sandbox Code Playgroud)

在图书馆的来源:

namespace std
{
    template class basic_string<wchar_t>;
}
Run Code Online (Sandbox Code Playgroud)

当然,您需要事先知道模板需要哪些实例化.显然,SO无法导出使用它一无所知的类型的实例化.

更新:啊,但你有两个不同的库即时模板...然后如果两个库定义显式实例化,因为extern共享ELF魔法应该将两个实例合并为一个.

另一个更新:使用模板和共享对象后,它通常只是工作.我现在的猜测是你正在编译-fvisibility=hidden或类似的库.如果是这样的话,那就写下来就足够了:

template <class OBJECT>
struct __attribute__((visibility("default"))) Container
{
   static int m_member;
};
Run Code Online (Sandbox Code Playgroud)

使模板的特化进入动态符号表,从而避免重复.