【问题标题】:Using exit and a global object使用 exit 和全局对象
【发布时间】: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 编译器

标签: c++


【解决方案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 进而调用 ...(是的,它会持续很长时间)。

    【讨论】:

      猜你喜欢
      • 2012-04-23
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      • 2014-12-20
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 2021-12-12
      相关资源
      最近更新 更多