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 では重複しません。

いずれにせよ、オペレーティング システムとプロジェクトのレイアウトに関する詳細を提供する必要があります。

更新:ああ、でもあなたのクラスはテンプレートです! 共有ライブラリでのテンプレートのインスタンス化は奇妙な獣です! すべてのプロセスでクラスのコピーが 1 つだけ使用されるようにするには、テンプレートを明示的にインスタンス化し、このインスタンス化が SO でエクスポートされ、クライアント コードから使用されるようにする必要があります。詳細はコンパイラによって異なりますが、次のように実行方法を確認できますstd::string

ヘッダー ファイル内:

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

ライブラリのソースで:

namespace std
{
    template class basic_string<wchar_t>;
}

当然、テンプレートのどのインスタンス化が必要になるかを事前に知る必要があります。明らかに、SO は、何も知らない型を使用するインスタンス化をエクスポートできません。

更新: ああ、しかし、テンプレートをインスタンス化する 2 つの異なるライブラリがあります...両方のライブラリexternが共有 ELF マジックとして明示的なインスタンス化を定義する場合、両方のインスタンス化を 1 つにマージする必要があります。

さらに別の更新: テンプレートと共有オブジェクトで遊んだ後、通常は機能します。私の推測では、ライブラリを-fvisibility=hiddenまたは類似のものでコンパイルしていると思います。その場合は、次のように書くだけで十分です。

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

テンプレートを特殊化してダイナミック シンボル テーブルに入力し、重複を回避します。

于 2012-07-26T09:27:05.573 に答える