【问题标题】:Why Calling exit() at Singleton's destructor is causing an infinite loop?为什么在 Singleton 的析构函数中调用 exit() 会导致无限循环?
【发布时间】:2016-11-10 12:08:16
【问题描述】:

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

【问题讨论】:

标签: c++ singleton infinite-loop destructor


【解决方案1】:

这不足为奇。

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

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

【讨论】:

    【解决方案2】:

    问:你的单例对象是什么时候销毁的? A:当进程退出时,要么显式调用exit(),要么退出main()函数。

    所以,不要在单例的析构函数中调用 exit()。你正在已经退出......

    【讨论】:

    • '不要在你的单例的析构函数中调用 exit()。你已经退出'UPVOTED
    【解决方案3】:

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

    在这些情况下,很可能存在未定义的行为。如果您因为调用exit() 而发生的某事调用exit(),那么您很可能会陷入无限循环。 不能保证,因为全局析构函数的处理可能会以这样一种方式完成,即首先将要销毁的事物列表从某些列表中删除,然后调用析构函数。因此,如果再次调用exit,它将处于“已经处理过这个对象”的状态。 标准当然没有说“你必须应对exit() 被多次调用 - 所以另一个 C++ 库很可能无法应对这个问题。

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

    【讨论】:

      猜你喜欢
      • 2013-06-17
      • 1970-01-01
      • 2020-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多