为什么在Singleton的析构函数中调用exit()会导致无限循环?

时间:2016-11-10 12:08:17

标签: c++ singleton infinite-loop destructor

在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()
....

3 个答案:

答案 0 :(得分:4)

这并不奇怪。

在调用sources.list期间,C ++运行时将析构函数调用到exit存储的所有对象。

如果你无法修复这个有问题的设计,那么在析构函数中加入一些东西来阻止递归。

答案 1 :(得分:3)

问:你的单身对象何时被摧毁? 答:当进程退出时,可以通过显式调用exit()或退出main()函数来退出。

所以,不要在你的单身人士的析构函数中调用exit()。您已退出...

答案 2 :(得分:0)

  

main()退出或标准C库函数exit()为时,将调用静态对象的析构函数(即,具有静态存储的所有对象,而不仅仅是上例中的本地静态对象)明确地叫。在大多数实现中,main()只在终止时调用exit()。这意味着在析构函数中调用exit()会很危险,因为最终可能会出现无限递归

在这些情况下,很可能存在未定义的行为。如果您因为调用exit()而发生的事件中的exit(),则可能会导致无限循环。 不能保证,因为全局析构函数的处理可以通过首先从列表中删除它然后调用析构函数来处理要销毁的事物列表。因此,如果再次调用exit,它将处于已经处理此对象的状态&#34;。 标准肯定不会说&#34;你必须多次处理exit()被调用 - 所以很可能另一个C ++库无法应对这个问题。

以下是gcc下的proof:没有任何无限循环。