2016-11-10 31 views
0

を呼び出すexit()は、シングルトンのデストラクタで無限ループを引き起こしていますが、これはシングルトンクラスでのみ起こり、他の場所では正常に動作します!これはコードです:なぜSingletonのデストラクタでexit()を呼び出すと無限ループが発生していますか?

#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; 
} 

出力:

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

gccは無限ループで潜るわけではありませんhttp://coliru.stacked-crooked.com/a/585f9ef22160ed67 –

答えて

4

はほとんど驚きです。

exitの呼び出し時に、C++ランタイムは、デストラクタをstaticストレージを持つすべてのオブジェクトに呼び出します。

この疑わしいデザインを修正できない場合は、デストラクタに何かを入れて再帰をブロックします。

3

Q:シングルトンオブジェクトはいつ破壊されますか? A:exit()を明示的に呼び出すか、main()関数を終了するかのいずれかによって、プロセスが終了します。

したがって、シングルトンのデストラクタでexit()をコールしないでください。あなたすでに...静的オブジェクトのための

+0

'あなたのシングルトンのデストラクタでexit()を呼び出さないでください。あなたはすでに' UPVOTED –

0

デストラクタ(つまり、静的記憶を持つすべてのオブジェクトではなく、上記の例のように、単にローカル静的オブジェクト)がmain()終了する場合や、標準Cと呼ばれているが出ていますライブラリ関数exit()が明示的に呼び出されます。ほとんどの実装では、main()は終了時にexit()を呼び出します。これは、ほとんどの場合未定義の動作は、これらのケースではありますが、無限再帰で終わることができますので、デストラクタ内exit()を呼び出すために危険なことができることを

を意味します。 exit()exit()と呼んで起きたことから何かを呼び出すと、無限ループに終わる可能性があります。 グローバルデストラクタの処理は、まずリストから削除してから、デストラクタを呼び出すことによって処理されるようにして、を保証するものではありません。したがって、exitが再び呼び出された場合、「既にこのオブジェクトを処理していた」状態になります。 。確かにあなたがexit()が複数回呼び出されているにも対応しなければならない」と言っていません 標準 - それは別のC++ライブラリはこれに対処するために失敗することは非常に可能です

ここではgccproofです:任意の無限ループなし。

関連する問題