【问题标题】:Will exit() or an exception prevent an end-of-scope destructor from being called?exit() 或异常会阻止调用范围结束的析构函数吗?
【发布时间】:2011-02-09 17:13:10
【问题描述】:

假设我有以下代码:

struct mytype
{
    ~mytype() { /* do something like call Mix_CloseAudio etc */ }
};

int main()
{
    mytype instant;

    init_stuff();

    start();

    return 0;
}

即使从 start() 内部的某处使用 exit(),是否也保证调用该析构函数?

【问题讨论】:

  • 异常会调用析构函数,exit() 不会。
  • 不完全是这种情况,但我在带有 GCC 的 Linux 上调用了静态对象的析构函数。

标签: c++ destructor exit


【解决方案1】:

如果调用exit,则不会调用析构函数。

来自 C++ 标准(§3.6.1/4):

调用函数

void exit(int);

<cstdlib> (18.3) 中声明会在不离开当前块的情况下终止程序,因此不会破坏任何具有自动存储持续时间的对象 (12.4)。如果在销毁具有静态存储持续时间的对象期间调用 exit 结束程序,则程序具有未定义的行为。

【讨论】:

  • 但是是否可以退出并调用析构函数?
【解决方案2】:

是的,调用exit()意味着不会调用析构函数:

调用函数 void exit(int); 在<cstdlib> (18.3) 中声明 终止程序而不离开 当前块,因此没有 自动销毁任何物体 储存期限 (12.4)。如果退出是 调用期间结束程序 用静态破坏对象 存储时间,程序有 未定义的行为。

另一方面,如果抛出异常,则将调用析构函数。这是 C++ 中异常安全的基础。

【讨论】:

    【解决方案3】:

    只要程序中的某些东西捕获了异常,异常就会调用析构函数。如果异常在没有被捕获的情况下退出 main() 函数,则标准不要求运行时展开堆栈以进行清理。

    使用一个

    try{
      // code
    }catch(...){ //that elipsis should actually appear in your code
                 //it doesn't mean I omitted code here.
      //code
    }
    

    在您的main() 函数中将保证捕获每个异常,并调用所有析构函数。

    【讨论】:

    • 不展开堆栈清理的后果是什么?如果您只是希望软件由于某些错误和throw std::runtime_error("Some error text") 而关闭并且不要抓住它。之前创建的每个对象都会被安全删除吗?
    猜你喜欢
    • 2011-10-26
    • 1970-01-01
    • 2013-11-07
    • 2017-11-17
    • 2018-09-15
    • 2022-09-23
    • 2020-07-19
    • 2021-11-19
    • 2019-01-06
    相关资源
    最近更新 更多