【问题标题】:Exceptions, stack unwinding, encapsulated heap memory, exit() [duplicate]异常,堆栈展开,封装的堆内存,exit() [重复]
【发布时间】:2014-01-01 20:07:43
【问题描述】:

当抛出异常时,抛出异常的块从堆栈中展开:

int main ()
{
    try
    {
        Object x; // doesn't throw
        Object y; // throws
        cout << "wonderful";
    }
    catch (...)
    {
        cout << "fail";
    }
}

Object在堆上分配构造内存并在销毁时正确释放它,那么应该没有内存泄漏,因为堆栈展开调用x的析构函数(不是y,但Object保证,当构造函数失败时,没有内存泄漏)。就目前而言,不是吗?

让我们深入探讨:

int main ()
{
    Object x; // doesn't throw
    double *d = new double[256*256*256]; // doesn't throw
    Object y; // throws
    cout << "wonderful";
    delete[] d;
}

由于受过良好的教育,我想自己清理垃圾,而不是让操作系统来做。我知道,每个现代操作系统都会自行删除程序的堆内存,该程序会意外终止(或预期,但没有显式释放)。所以在大写的情况下,d 的释放会执行我的操作系统,但x 仍会正确释放其内存(因为堆栈展开和析构函数调用)之前操作系统会这样做,对吧?

那又怎样:

#include <cstdlib>

int main ()
{
    Object x; // doesn't throw
    try { Object y; } // throws
    catch (...) {  cout << "fail"; exit(EXIT_FAILURE); }
    cout << "working and working...";
    cin.get();
}

x 的析构函数是否被调用之前 exit 将控制权交还给操作系统?

更深入:

void Object::be_stupid ()
{
    Object a; // doesn't throw
    try { Object b; }// throws
    catch (...) { exit(EXIT_FAILURE); }
}

void main ()
{
    Object x; // doesn't throw
    try { x.be_stupid(); } // exits program
}

x 的构造函数是否调用了 before exit 将控制权交还给操作系统?如果是,那么exit“展开”所有周围的堆栈,包括main(),对吗?

【问题讨论】:

  • exit 不会像异常抛出那样展开。但是,正如您所说的那样,您的程序即将死去,它真的不需要。其他“立即死亡”函数也是如此,例如 std::terminate。
  • @polkadotcadaver:虽然资源被操作系统清理,但仍然需要销毁对象,例如,刷新缓冲流。但是,exit() 确实没有进行任何本地清理(它仍然清理全局对象)。
  • @DietmarKühl 我同意 - 总是更好地优雅地处理清理,尤其是在使用 RAII 比 new/delete 更具想象力的情况下。
  • 您可以查看this answer。它详细解释了 throws 如何导致内存泄漏。
  • @mb84 将 main 声明为 int main() 而不是退出只是返回,然后一切都会像离开任何函数时一样被清理,程序也会退出并清理静态对象.

标签: c++ exception heap-memory exit stack-unwinding


【解决方案1】:

好的,感谢 polkadotcadaver:永远不要使用 exit(),传播异常直到 main() 并在那里做一个简单的 return - 所有堆栈 Objects 将被它们自己的析构函数释放 之前 em> 操作系统取得控制权。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-15
    • 1970-01-01
    • 2021-04-07
    • 2012-09-23
    • 1970-01-01
    • 2020-11-14
    • 2014-04-17
    相关资源
    最近更新 更多