2012-07-26 6 views
5

Ich habe eine Multithread-Anwendung. Ich deklariere eine Klasse mit einem statischen Mitglied in einer gemeinsam genutzten Bibliothek.zwei Instanzen eines statischen Mitglieds, wie könnte das sein?

Drucken der Adresse des Elements von verschiedenen Threads aus verschiedenen Bibliotheken zeigt unterschiedliche Ergebnisse.

// Deklaration

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

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

// Druck

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

Wie konnte das sein?

+0

Wenn Sie verschiedene Threads aus verschiedenen Bibliotheken sagen, meinen Sie, dass Sie einen Prozess haben, der mehrere Threads hat, die auf das Mitglied zugreifen? Wenn ich mich richtig erinnere, habe ich gehört, dass shared libraries pro Prozess instanziiert werden, so dass jeder Prozess seine eigene Version hat (um andere Prozesse nicht zu stören). – Nobody

+1

Wie verlinken Sie die "shared library"? –

+0

Es ist ein Prozess mit mehreren Threads. Das Mitglied ist in der Header-Datei definiert (In meinem realen Code ist Container templated), aber ich bin mir ziemlich sicher, dass dies nicht das Problem ist. – Ezra

Antwort

4

Wenn Sie verschiedene Bibliotheken haben (ich vermute, verschiedene dynamische Bibliotheken), dann haben Sie möglicherweise einige Doppelkopie von Code und statischen Variablen.

Die genauen Details hängen von der jeweiligen dynamischen Bibliothekstechnologie ab, die Sie verwenden. Ich würde sagen, dass Sie beispielsweise in Windows DLLs Code und Variablen dupliziert haben, aber in Linux SOs nicht.

Wie auch immer, sollten Sie mehr Details über das Betriebssystem und das Layout Ihres Projekts geben.

UPDATE: Ahh, aber Ihre Klasse ist eine Vorlage! Template-Instanziierungen in einer gemeinsamen Bibliothek sind ein seltsames Biest! Um sicherzustellen, dass nur eine Kopie Ihrer Klasse für den gesamten Prozess verwendet wird, müssen Sie die Vorlage explizit instanziieren und sicherstellen, dass diese Instanziierung in die SO exportiert und aus dem Clientcode verwendet wird. Die Details variieren mit dem Compiler, aber Sie können überprüfen, wie die std::string erfolgt, zum Beispiel:

In der Header-Datei:

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

In der Quelle der Bibliothek:

namespace std 
{ 
    template class basic_string<wchar_t>; 
} 

Natürlich müssen Sie im Voraus wissen, welche Instanziierungen Ihrer Vorlage benötigt werden. Offensichtlich kann die SO keine Instanziierung exportieren, die einen Typ verwendet, von dem sie nichts weiß.

UPDATE: Ahh, aber Sie haben zwei verschiedene Bibliotheken die Vorlage instantating ... dann, wenn beide Bibliotheken die explizite Instanziierung als extern die gemeinsam genutzte ELF Magie definieren beiden Instanzen zu einer Einheit verschmelzen soll.

NOCH EIN WEITERES UPDATE: Nach dem Spielen mit Vorlagen und geteilten Objekten funktioniert es normalerweise einfach. Ich rate jetzt, dass Sie die Bibliotheken mit -fvisibility=hidden oder ähnlichem kompilieren. Wenn das der Fall ist, würde es ausreichen, nur zu schreiben:

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

Um die Spezialisierungen der Vorlage machen die dynamische Symboltabelle einzugeben und damit die Doppelarbeit vermeiden.

+0

Ich benutze Linux CentOS, also SO. Soweit ich weiß, sollte es nur eine Instanz von Container :: m_member geben. – Ezra

+0

+1. Ich habe jedoch Ihre Vorschläge ausprobiert und immer noch zwei Instanzen erhalten. Wenn das einen Hinweis geben könnte: Die Adressen, die ich sehe, haben unterschiedliche Längen: 0x61bdb0, 0x2aaaab92d5b0. Meine Maschine ist 64bit. – Ezra

+0

@Ezra: Ich habe ein Beispiel gemacht und war in der Lage, beide Ergebnisse (gleiche Adresse oder andere Adressen) nur mit den Sichtbarkeitsoptionen zu spielen. Sie sollten wirklich kompilierbaren Code und die Compilerbefehle, die Ihr Problem reproduzieren, veröffentlichen. – rodrigo

Verwandte Themen