2016-11-10 2 views
0

Aufruf von exit() in Singleton Destruktor verursacht eine Endlosschleife, das passiert nur mit der Singleton-Klasse und es funktioniert gut woanders! Dies ist der Code:Warum ruft exit() in Singletons Destruktor eine Endlosschleife auf?

#include <iostream> 
#include <stdlib.h> 
class Singleton{ 
     private : 
     Singleton(){} 
     public : // public destructor , allow 'delete' or whatever , not our subject 
     ~Singleton() 
     { 
     std::cout<<"~Singleton()"<<std::endl; 
     exit(0);    
     } 
     static Singleton * GetInstance() 
     { 
     static Singleton s; 
     return &s;  
     } 
     }; 
int main() 
{ 
    // Signleton s; , this is safe when the constructor is public 
    Singleton::GetInstance(); // this enter an infinate loop 
    return 0; 
} 

Ausgang:

~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
~Singleton() 
.... 
+0

Beachten Sie, dass gcc nicht in der Endlosschleife abtaucht http://coliru.stacked-crooked.com/a/585f9ef22160ed67 –

Antwort

4

das kaum überraschend.

Während des Aufrufs an 10 ruft die C++ - Laufzeit die Destruktoren für alle Objekte mit static Speicher auf.

Wenn Sie dieses fragwürdige Design nicht reparieren können, setzen Sie etwas in den Destruktor, um die Rekursion zu blockieren.

3

F: Wann ist Ihr Singleton-Objekt zerstört? A: Wenn der Prozess beendet wird, indem exit() explizit aufgerufen wird oder die main() -Funktion beendet wird.

Also, rufen Sie exit() im Destruktor Ihres Singleton nicht auf. Sie sind schon beendet ...

+0

'rufen Sie exit() im Destruktor Ihres Singleton nicht auf. UPVOTED –

0

Destruktoren für statische Objekte (dh alle Objekte mit statischen Speichern, nicht nur lokale statische Objekte, wie im Beispiel oben) aufgerufen werden, wenn main() austritt, oder wenn das Standard-C Bibliotheksfunktion exit() wird explizit aufgerufen. In den meisten Implementierungen ruft main() nur exit() auf, wenn es beendet wird. Das bedeutet, dass es gefährlich sein kann exit() in einem destructor zu nennen, weil Sie mit unendlicher Rekursion können am Ende

Wahrscheinlich ist es undefiniertes Verhalten in diesen Fällen. Wenn Sie exit() von etwas aufrufen, das passiert ist, weil Sie exit() aufgerufen haben, besteht die Möglichkeit, dass Sie in einer Endlosschleife enden. Es ist nicht garantiert, weil die Behandlung der globalen Destruktoren in einer solchen Weise erfolgen kann, dass die Liste der Dinge, die zerstört werden sollen, behandelt wird, indem sie zuerst aus der Liste entfernt wird und dann der Destruktor aufgerufen wird. Wenn also erneut aufgerufen wird, befindet es sich in einem Zustand, in dem es "dieses Objekt bereits behandelt hat". . Der Standard sicherlich nicht sagen, „Sie bewältigen müssen mit exit() mehrmals aufgerufen werden - so ist es durchaus möglich, dass eine andere C++ Bibliothek wird dies zu bewältigen scheitern

Hier ist die proof unter gcc: ohne Endlosschleife.

Verwandte Themen