2016-11-09 3 views
0

Ich habe eine statische Variable in einer Funktion Template-Klasse wie folgt aus:statische Variable in Funktion Template-Klasse durch die globale statische Variable überschrieben

template<class T> 
struct builder 
{ 
    static T* buildOrGet() 
    { 
     static T* built = nullptr; 
     if(built == nullptr) built = new T; 
     return built; 
    } 
}; 

und an anderer Stelle im Code eine globale Variable mit einem Konstruktor.

static SomeClass global_var; 

Zuerst wusste ich nicht, was passiert ist, aber das built Variable wurde ohne Grund an einem bestimmten Punkt des Programms beschädigt. Dann fügte ich einen 4-Byte-Datenhaltepunkt in Visual Studio auf &built hinzu, um zu sehen, wer seinen Speicher nach built = new T; zertrümmerte, und tatsächlich ist es während des C++ - Initialisierers beim Initialisieren von Elementen von global_var im SomeClass-Konstruktor. Der Code ist in einer DLL, automatisch geladen von einer exe abhängig davon. Es ist wie global_var Speicherüberschneidungen built Speicher, der sehr seltsam ist.

Ich verstehe wirklich nicht warum und wie das außer einem Fehler in Visual Studio 2015 passieren kann, können Sie mir helfen?

+0

Können Sie mehr Details, insbesondere über SomeClass geben? Gibt es insbesondere eine Möglichkeit, dass ein illegaler Schreibvorgang in seinem Konstruktor passiert? – Eternal

+0

in der Tat 'SomeClass' hat einige Daten Mitglieder, und wenn der Daten Breakpoint ausgelöst wurde sah ich die Adresse seiner Mitglieder für die aktuelle Instanz und einer von ihnen war die Adresse von' Built' + 1, bedeutet der Speicher von der 'besetzt global_var' überlappt den eingebauten Speicher. Und Mitglieder werden nur initialisiert, sie überschreiben keinen Speicher (in der Assembly entspricht der Code, an dem der Breakpoint ausgelöst wird, der Initialisierung des Members: etwas wie: move rcx this mov rcx + 28h 0 <- Datenhaltepunkt wird hier ausgelöst – Juicebox

+0

I Wetten, was Sie hier beschreiben, ist eigentlich kein Problem selbst, sondern eine Konsequenz einer Speicherbeschädigung (die irgendwo zuvor passiert). –

Antwort

0

fand ich die Lösung: In der Tat habe ich in verschiedenen Übersetzungseinheiten meiner dll mehr global_var mit dem gleichen Namen habe, aber sie haben nicht die gleiche Art (die anderen int Typen lassen sagen hat).

In diesem Fall (das ist seltsam für mich, weil sie "statisch" sind), halten Sie den Linker nur und verwenden Sie den gleichen Speicher für alle Variablen (es hielt hier die int eins).

Dies ist, wo es schief geht ... Die Someclass Konstruktor noch für die global_var rief ich oben erwähnt, aber der Speicher ist nicht sizeof(SomeClass), aber sizeof(int) und das ist, wo der Überlauf passiert.

Für mich ist es ein Fehler, weil der Linker mich über diese homonymen Variablen mit verschiedenen Typen oder/bemerkt haben sollte und es vermeiden sollte, einen Konstruktor für eine Variable aufzurufen, die nicht mit dem konstruierten Speicher übereinstimmt.

Die Lösung ist: niemals zwei statische Variable mit dem gleichen Namen in verschiedenen Übersetzungseinheiten deklarieren, nur eine wird überleben und Sie können nicht erraten, welche.

+0

Wenn Sie eine statische Variable im globalen Geltungsbereich deklarieren, bedeutet das Schlüsselwort 'static', dass die Variable von anderen Übersetzungseinheiten nicht zugänglich sein soll (um Namenskonflikte zu vermeiden) . Der Linker, der keine Warnung ausgibt, ist normal. Was ich nicht verstehe, ist, warum nur 'sizeof (int)' in der Übersetzungseinheit zugewiesen wurde, in der 'global_var' vom Typ' SomeClass' ist. – Eternal

+0

Das habe ich auch seltsam gefunden, aber es ist der Fall ... wann Ich gucke '& global_var' im Debugger Ich habe sagen' 0x20', wenn ich darauf bringe und ich gebe seinen Konstruktor ein, 'this' sollte' 0x20' sein, richtig? Aber ** es ist nicht **, es ist, als ob die Konstruktion woanders stattfindet, nicht auf der 'global_var', die ich gesehen habe, und hier begann ich mich selbst zu fragen, welche Optimierung im Linker passiert ist ... und es scheint, dass es" verschmilzt " "homonyme Variable Initialisierung oder so ähnlich. Nur den Namen zu ändern löste mein Problem. – Juicebox

Verwandte Themen