2013-04-15 13 views
14

frage ich mich, dass um zwischen Zerstörung des globalen Objekts und atexit in C sure kann ++Auftrag zwischen Zerstörung des globalen Objekts und atexit in C++

ich ein globales Objekt haben und registrieren atexit Funktion wie unten:

static MyClass g_class; 

void onExit() 
{ 
    // do some destruction 
} 

int main() 
{ 
    atexit(onExit); 

    return 0; 
} 

Ich habe gefunden onExit() wird vor MyClass::~MyClass() in Visual Studio 2012 und gcc4.7.2 aufgerufen. Bin ich sicher, dass onExit immer vor einem globalen Objekt (wie g_class) Zerstörung aufgerufen wird?

Ich wundere mich global Objekt registrieren und atexit Registerauftrag verwenden gleichen Auftrag Tabelle. Oder gibt es keine Beziehung zwischen globalen Objekt Reihenfolge und atexit Reihenfolge?

Bearbeitet: Leider habe ich einen Fehler geschrieben. Ich bin so verwirrt, während ich Beispielcode aufräume. onExit() wird vor ~ MyClass() aufgerufen.

+0

Ich vermute, dass Reihenfolge nicht 100% sicher ist, definiert zu werden. Warum kümmert dich das? –

+0

Erstellen Sie ein weiteres globales Objekt vor 'MyClass' und rufen Sie' atexit (onExit) 'in seinem Konstruktor auf, um es zu überprüfen. – lapk

+1

Möchten Sie die Lebensdauer von Objekten steuern, verwenden Sie dynamische Objekte. – PiotrNycz

Antwort

14

UPDATE:Das OP machte einige Verwirrung, und es scheint, VC11 verhält sich tatsächlich wie durch den C++ 11 Standard spezifiziert. Die folgende Antwort wurde in der Annahme geschrieben, dass dies nicht der Fall war.

Daher ist die Antwort auf diese Frage:

Bin ich sicher, dass onExit immer vor (wie g_class) Zerstörung globale Objekt aufgerufen wird?

Ist "Ja", solange Sie mit einem voll-kompatibelen Compiler arbeiten.


ich gefunden habe MyClass::~MyClass() vor onExit() in Visual Studio aufgerufen 2012.

Wenn dies der Fall ist, dann ist es ein Bug in VC11. 3.6.3/1 des C++ 11 Standard pro Absatz:

Destructors (12.4) für initialisierte Objekte (dh Objekte, deren Lebensdauer (3.8) hat begonnen) mit statischen Speicher Dauer als eine angerufene Ergebnis der Rückkehr von main und als Ergebnis des Aufrufs std::exit (18.5). [...]

Auch pro Paragraph 3.6.3/3:

Wenn der Abschluss der Initialisierung eines Objekts mit statischen Lagerdauer vor einem Aufruf zu std::atexit sequenziert (siehe <cstdlib>, 18.5), Der Aufruf der Funktion, die an std::atexit übergeben wird, wird vor dem Aufruf des Destruktors für das Objekt sequenziert.

daher in Ihrem Fall onexit() sollte vor dem destructor von MyClass aufgerufen werden.

So weit ich sagen kann, sind Clang 3.2 und GCC 4.8.0 in dieser Hinsicht konform, wie in dieser live example gezeigt.

+0

Ob g ++ kompatibel ist oder nicht, hängt von den Compileroptionen und der Plattform ab. (Es ist kompatibel, wenn es sein kann, aber da auf vielen Plattformen die 'atexit'-Funktion von der Plattform bereitgestellt wird, ist dies nicht immer vernünftig möglich.) –

+0

Entschuldigung. Ich habe einen Fehler geschrieben. onexit() wird vor ~ MyClass aufgerufen. Ich war so verwirrt, während ich Beispielcode aufräumte. – zelon

+2

@zelon: OK. Dann ist das Verhalten korrekt und das ist was der C++ Standard spezifiziert. –