使用 exit 和全局对象

Posted

技术标签:

【中文标题】使用 exit 和全局对象【英文标题】:Using exit and a global object 【发布时间】:2012-04-30 05:57:33 【问题描述】:

我有以下程序,我在析构函数中调用 exit()。当我在 main() 中创建一个 sample 类型的对象时,析构函数被调用一次并且程序正常退出。但是当我创建一个样本类型的全局对象时,“Destructing..”会被无限打印出来。谁能解释一下?

#include "iostream"
#include "conio.h"

using namespace std;

class sample

      public:
     ~sample() 
                    cout <<"Destructing.."<<endl;
                    exit(0);
                
;

sample obj;

int main()

 getch();   

【问题讨论】:

可能你使用的是turboc,请避免使用,不要使用conio.h函数。 M 使用 Dev-C++ 。它使用 GCC 编译器 【参考方案1】:

发生的事情是,exit() 函数正在让程序调用所有全局对象的析构函数。并且由于在您的类的析构函数调用exit(1); 时,该对象还没有被认为是被析构的,析构函数被再次调用,导致无限循环。

你可以摆脱这个:

class sample 
    bool exiting;
public:
    sample()  exiting = false; 
    ~sample() 
        cout << "Destructing.." << endl;
        if(exiting) return;
        exiting = true;
        exit(0);
    
;

但是调用 exit() 的析构函数是个坏主意。考虑以下备选方案之一:

为退出创建一个单独的普通(非析构函数)方法 创建一个一直运行到“程序”完成的函数并从main()调用它 使用abort() 而不是exit()(感谢金发姑娘提到这一点)。 abort() 绕过通常在调用exit()main() 返回时完成的所有清理工作。然而,这也不一定是一个好主意,因为程序中的某些清理操作可能非常关键。 abort() 仅适用于已经严重到需要绕过清理的错误。

我之前建议过异常,但记得从析构函数内部抛出异常并改变了主意。 here's why.

另请注意,行为并不一致 - 一些编译器/环境会导致无限循环,而另一些则不会。它归结为在析构函数中的哪个点对象被认为被销毁。我猜这个标准要么没有涵盖这一点,要么说这种情况下的行为是未定义的。

【讨论】:

为什么我没有得到与提问者相同的效果? 因为你的编译器可能更聪明 即使使用-O0gcc,我也会打印一行。 另外,如果它为全局打印多行,那为什么不本地呢。 本地析构函数在其函数退出时被调用。我将展开以涵盖这一点。【参考方案2】:

我同意 Micheal Slade 的观点,即在析构函数中这样做是糟糕设计的标志。但是,如果您认为您有充分的理由这样做(例如,开发问题),请使用abort() 而不是exit(0)。这将阻止调用任何更多的析构函数并让您退出递归循环。

【讨论】:

【参考方案3】:

您的破坏性析构函数调用 exit 进而调用破坏析构函数调用 exit 进而调用 ...(是的,它会持续很长时间)。

【讨论】:

以上是关于使用 exit 和全局对象的主要内容,如果未能解决你的问题,请参考以下文章

Node.js的全局对象和全局变量

Node.js全局对象

在 System.exit(0) 处解除绑定

JavaScript中的全局对象,内置对象和预定义对象是啥?

静态对象和全局对象的销毁顺序是啥?

javaScript 对于全局对象对象的理解