【问题标题】:Ways to avoid memory leak when exception thrown抛出异常时避免内存泄漏的方法
【发布时间】:2016-03-19 10:47:51
【问题描述】:

这是 C++ Primer 第 18 章中的一个练习:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    int *p = new int[v.size()];
    ifstream in("ints");
    // exception occurs here
}

上面的代码会导致内存泄漏,因为我们直接管理的内存(即p)在异常发生时不会自动释放。

练习 18.3:

如果抛出异常,有两种方法可以使前面的代码正常工作。描述它们并实施它们。

我知道我们可以使用智能指针来避免这个陷阱:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    unique_ptr<int[]> p(new int[v.size()]);
    ifstream in("ints");
    // exception occurs here
}

或:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    shared_ptr<int> p(new int[v.size()], [](int *p){ delete[] p; });
    ifstream in("ints");
    // exception occurs here
}

我不确定这些是否是TWO 方式。毕竟,它们实际上是相同的。于是我想到了另一种方式:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    int *p = new int[v.size()];
    ifstream in("ints");
    // exception occurs here
    if(!in)
        throw p;
}

// caller
try {
    exercise(b, e);
} catch (int *err) {
    delete[] err; // initialize err with b and delete e.
}

如果发生异常,抛出p 来初始化另一个指针并删除那个指针。我知道这不是一个完美的解决方案,因为可能会发生其他异常,所以我什至没有机会抛出p。但我想不出更好的了。你能帮忙找到第二种方法吗?

【问题讨论】:

  • 对函数中的所有内容 (...) 进行简单的 try-catch 怎么样?删除并重新抛出那里。 ... 或者,也可以为p 使用向量?
  • 哦,是的,rethrow 更适合这个问题。谢谢!
  • 你忘了vector&lt;int&gt;p(v.size());

标签: c++ exception memory-leaks


【解决方案1】:

您可以显式捕获并重新抛出异常:

void exercise(int *b, int *e)
{
    vector<int> v(b, e);
    int *p = new int[v.size()];
    try {
        ifstream in("ints");
        // exception occurs here
    } catch (...) {
        delete[] p;
        throw;
    }
    delete[] p;
}

当然,如果您有多个要释放的资源,这不会很好地工作,因为您最终可能会得到嵌套的 try/catch 块。更不用说你有两个deletes 一个new。所以首选RAII。

【讨论】:

    猜你喜欢
    • 2014-07-31
    • 2017-05-16
    • 2014-12-15
    • 2013-07-22
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    相关资源
    最近更新 更多