2012-07-26 7 views
5

私はマルチスレッドアプリケーションを持っています。 共有ライブラリに静的メンバーを持つクラスを宣言します。静的メンバーの2つのインスタンス、どのようにすることができますか?

異なるライブラリの異なるスレッドからメンバのアドレスを表示すると、異なる結果が表示されます。

//宣言

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

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

//

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

がどのようにそれは可能性があり、印刷?

+0

異なるライブラリから異なるスレッドを言うと、メンバーにアクセスする複数のスレッドを持つ1つのプロセスがあることを意味しますか?私が正しく覚えていれば、共有ライブラリはプロセスごとにインスタンス化されるので、各プロセスは独自のバージョン(他のプロセスを妨害しない)を持っていると聞きました。 – Nobody

+1

「共有ライブラリ」はどうやってリンクしていますか? –

+0

これは、複数のスレッドを持つ1つのプロセスです。メンバーはヘッダーファイルで定義されています(私の実際のコードではContainerはテンプレート化されています)が、これは問題ではないと確信しています。 – Ezra

答えて

4

異なるライブラリがある場合(私は異なるダイナミックライブラリを推測しています)、コードと静的変数の両方が重複している可能性があります。

正確な詳細は、使用している特定のダイナミックライブラリテクノロジによって異なります。私は、たとえば、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は、何も知らない型を使用するインスタンス化をエクスポートできません。

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

その他のアップデート:テンプレートと共有オブジェクトを使用して再生した後、通常は機能します。私の推測では、-fvisibility=hiddenなどのライブラリをコンパイルしています。

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

は、ダイナミックシンボルテーブルを入力するために、テンプレートの特殊化を行うために、したがって、重複を避ける:その場合は、それだけで書くには十分だろう。

+0

私はLinux CentOSを使用しています。私が知る限り、Container :: m_memberのインスタンスは1つだけです。 – Ezra

+0

+1。しかし、私はあなたの提案を試みたが、まだ2つのインスタンスを取得しています。それがヒントを与えることができれば:私が見ているアドレスは異なった長さである:0x61bdb0、0x2aaaab92d5b0。私のマシンは64ビットです。 – Ezra

+0

@エズラ:私は例を見て、両方の結果(同じアドレスまたは異なるアドレス)を表示オプションで再生することができました。コンパイル可能なコードと問題を再現するコンパイラコマンドを実際に投稿するべきです。 – rodrigo

関連する問題