6

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

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

//宣言

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

template <class OBJECT>
int Container<OBJECT>::m_member;

// 印刷

cout << (void*) &Container<int>::m_member << endl;

怎么可能?

4

1 回答 1

6

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

确切的细节将取决于您使用的特定动态库技术。我会说,例如,在 Windows DLL 中,您将拥有重复的代码和变量,但在 Linux SO 中则不会。

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

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

在头文件中:

namespace std
{
    extern template class basic_string<wchar_t>;
}

在库的源代码中:

namespace std
{
    template class basic_string<wchar_t>;
}

当然,您需要提前知道您的模板需要哪些实例化。显然,SO 不能导出使用它一无所知的类型的实例化。

更新:啊,但是您有两个不同的库来实例化模板……那么如果两个库都将显式实例化定义为extern共享的 ELF 魔术,则应该将两个实例化合并为一个。

另一个更新:在使用模板和共享对象之后,它通常可以正常工作。我现在的猜测是您正在使用-fvisibility=hidden或类似的方式编译库。如果是这种情况,只需编写以下代码就足够了:

template <class OBJECT>
struct __attribute__((visibility("default"))) Container
{
   static int m_member;
};

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

于 2012-07-26T09:27:05.573 回答