抛出异常时避免内存泄漏的方法

时间:2015-12-14 02:19:42

标签: c++ exception memory-leaks

这是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。但我无法想到更好的一个。你能帮忙找到第二种方式吗?

1 个答案:

答案 0 :(得分:4)

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

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块。更不用说一个delete有两个new个。所以RAII是首选。