2015-12-14 15 views
6

Questo è un esercizio da C++ Primer, capitolo 18:modi per evitare perdita di memoria quando eccezione generata

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

Il codice di cui sopra potrebbe causare perdita di memoria, perché la memoria gestiamo direttamente (cioè p) non è automaticamente liberato quando si verifica un'eccezione.

Esercizio 18.3:

Ci sono due modi per rendere il lavoro precedente codice correttamente se viene generata un'eccezione. Descrivili e implementali.

So che possiamo usare puntatore intelligente per evitare questa trappola:

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 
} 

o:

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 
} 

non sono sicuro se queste sono TWO modi. Dopotutto, sono praticamente gli stessi. Così ho pensato ad un altro modo:

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

Se si verifica un'eccezione, gettare p per inizializzare un altro puntatore ed eliminare quello. So che questa non è una soluzione perfetta, perché potrebbero verificarsi altre eccezioni in modo che io non abbia nemmeno la possibilità di lanciare p. Ma non riesco a pensarne uno migliore. Potresti aiutare a trovare il secondo modo?

+1

Che ne dici di un semplice try-catch per tutto ('...') all'interno della funzione? Elimina e rilancia lì. ... Oppure, che ne dici di usare un vettore anche per 'p'? – deviantfan

+0

Oh, sì, 'rethrow' è molto meglio per questo problema. Grazie! – chihyang

+1

Stai dimenticando 'vector p (v.size());' –

risposta

4

È possibile catturare in modo esplicito e ri-generare l'eccezione:

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

Naturalmente questo non funziona così bene se si dispone di più risorse per libero, perché si può finire con i blocchi try/catch nidificato . Per non parlare del fatto che hai due delete s per uno new. Quindi RAII è preferito.