Frage

Ich habe ein seltsames Verhalten mit einer einfachen C ++ Klasse angetroffen werden.

classA.h

class A
{
public:
  A();
  ~A();
  static const std::string CONST_STR;
};

classA.cpp

#include "classA.h"
#include <cassert>

const std::string A::CONST_STR("some text");

A::A()
{
  assert(!CONST_STR.empty()); //OK
}

A::~A()
{
  assert(!CONST_STR.empty()); //fails
}

main.cpp

#include <memory>  
#include <classA.h>  

std::auto_ptr<A> g_aStuff; 

int main() 
{ 
  //do something ... 
  g_aStuff = std::auto_ptr<A>(new A()); 
  //do something ... 
  return 0; 
}

Ich würde erwarten, dass Zugriffsverletzungen oder ähnliches, aber ich würde nie erwarten, dass der Inhalt des statischen const String ändern könnte. Hat jemand hier eine gute Erklärung haben, was in diesem Code passiert?

Danke, Norbert

War es hilfreich?

Lösung

  

Ich würde erwarten, Zugriffsverletzungen oder   etwas Ähnliches, aber ich würde nie erwarten   dass der Inhalt des statischen const   String könnte sich ändern.

undefiniertes Verhalten: es ist nicht definiert. Wenn CONST_STR zerstört wurde, dann sind Sie nicht eine Hardware-Ausnahme garantiert, wenn Sie darauf zugreifen. Es könnte abstürzen, aber dann wieder seine Adresse kann Daten enthalten, die am Ende wie eine leere Zeichenkette aussieht:. Destruktor Zeiger löschen könnte oder was auch immer

In diesem Fall sagen, dass die A-Instanz auch in einem globalen Smart-Pointer gespeichert, die in Haupt zugeordnet ist (). So ist die CONST_STR konstruiert worden ist, wenn es in dem A-Konstruktor zugegriffen wird, aber möglicherweise zerstört wird, bevor der Smart-Pointer zerstört wird. Wir würden das ganze Programm brauchen, um sicher zu sagen.

[Edit: Sie haben das getan. Da CONST_STR und g_aStuff in verschiedenen Übersetzungseinheiten definiert sind, ist ihre relative Reihenfolge des Aufbaus nicht durch den Standard definiert. Ich vermute, dass CONST_STR zuerst zerstört wird.]

Andere Tipps

Bearbeiten: Anscheinend ist der fehlende A:: war ein Tippfehler in der ursprünglichen Nachricht des Codes.

Original Antwort:

Haben Sie vor haben


    const std::string A::CONST_STR("some text");

, so dass die CONST_STR ist Teil der Klasse A?

Ansonsten werden Sie es separat und nicht Initialisierung des statischen Member von A erklärt.

Sie erstellen 2 statische Variablen in zwei verschiedenen Übersetzungseinheiten. Es gibt keine Möglichkeit zu sagen, in welcher Reihenfolge sie initialisiert werden. Aber ihre Destruktoren sind immer in umgekehrter Reihenfolge genannt.

In Ihrem Fall scheint es, dass im nächsten Szenario stattfindet:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

CONST_str destructor 
g_aStuff descrutor  

An diesem Punkt Ergebnis CONST_STR.empty () ist nicht definiert. Welche assert auslösen können.

Das

in classA.cpp definiert
const std::string CONST_STR("some text");
ist kein Mitglied von A. Diese Definition aussehen würde:

const std::string A::CONST_STR("some text");

Die Norm legt nicht die Reihenfolge der Initialisierung der globalen / statischer Objekte in verschiedenen Übersetzungseinheiten. Es ist, garantiert jedoch, dass jedes solches Objekt initialisiert werden, bevor eine Funktion von dieser Übersetzungseinheit ausgeführt wird.

In Ihrem Fall passiert es, dass CONST_STR nach g_aStuff initialisiert und, da die Reihenfolge der Zerstörung umgekehrt aus der Ordnung der Konstruktion ist es, bevor es zerstört wird. So ruft nicht definiertes Verhalten CONST_STR von A Destruktor Zugriff -. Sie können eine Zugriffsverletzung oder Sie vielleicht nicht

CONST_STR wird jedoch vor A Konstruktor initialisiert wird ausgeführt, weil sie in derselben Übersetzungseinheit ist.

Es kann passieren, wenn es eine globale Instanz von A (oder ein statisches Klassenmitglied vom Typ A). Da die Reihenfolge der Initialisierung von Globals und Statik nicht (Querübersetzungseinheiten) definiert ist, kann es sein.

auf Ihren vollständigen Code suchen, sind Sie in der Größenordnung von Zerstörung über Übersetzungseinheiten hinweg (classA.cpp und main.cpp) angewiesen zu sein. Wenn Sie g_aStuff als lokal in Haupt schaffen sie, sie behauptet passieren soll.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top