2015-12-14 2 views
6

Этого упражнения из 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

Как насчет простой try-catch для всего ('...') внутри функции? Удалите и восстановите там. ... Или, как насчет использования вектора для 'p' тоже? – deviantfan

+0

О, да, 'rethrow' намного лучше справляется с этой проблемой. Спасибо! – chihyang

+1

Вы сбрасываете 'vector p (v.size());' –

ответ

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; 
} 

Конечно, это не работает так хорошо, если у вас есть несколько ресурсов, чтобы свободно, потому что вы можете в конечном итоге с вложенными блоками попытка/улове , Не говоря уже о том, что у вас есть два delete s для одного new. Поэтому RAII является предпочтительным.