Domanda

Stavo discutendo con alcuni colleghi su ciò che accade quando si lancia un'eccezione in una classe allocata dinamicamente. So che malloc viene chiamato, e poi il costruttore della classe. Il costruttore non ritorna mai, quindi cosa succede al malloc?

Si consideri il seguente esempio:

class B
{
public:
    B()
    {
        cout << "B::B()" << endl;
        throw "B::exception";
    }

    ~B()
    {
        cout << "B::~B()" << endl;          
    }
};

void main()
{
    B *o = 0;
    try
    {
        o = new B;
    }
    catch(const char *)
    {
        cout << "ouch!" << endl;
    }
}

Cosa succede al o di memoria malloced, ci si perde? Ha CRT cattura l'eccezione del costruttore e deallocare la memoria?

Cheers!
Ricco

È stato utile?

Soluzione

Una chiamata a

new B();

risolve in due cose:

  • imputare con un operatore new () (sia globale uno o uno specifico classe, potenzialmente un posizionamento uno con l'new (xxx) B() sintassi)
  • chiamando il costruttore.

Se il tiro del costruttore, l'operatore corrispondente eliminazione viene chiamato. Il caso in cui il corrispondente di eliminazione è un collocamento è l'unico caso in cui un collocamento eliminare operatore è chiamato senza la sintassi :: operator delete (). delete x; o delete[] x; non chiamare il posizionamento cancellare gli operatori e non c'è una sintassi simile alla nuova collocazione a chiamarli.

Si noti che mentre il distruttore di B sarà non essere chiamato, già costruiti sottooggetti (membri o B e di base classi di B) sarà distrutto prima della chiamata all'operatore cancellare. Il costruttore che non si chiama è quello per B.

Altri suggerimenti

Quando viene generata un'eccezione dal costruttore, la memoria allocata da nuovo viene rilasciato, ma il distruttore della classe B non viene chiamato.

In questo caso, l'oggetto, o, in realtà non ottenere costruito, e la memoria allocata da new viene liberato. Come tale, il distruttore non viene chiamato. Quindi non c'è bisogno di chiamare:

delete o;

Un design pattern interessante è RAII - Risorsa acquisizione è di inizializzazione. In questo modello, si utilizza un costruttore per incapsulare l'acquisizione di una risorsa, e rilasciare la risorsa nel distruttore. Se la risorsa non può essere acquisita, si butta nel costruttore - tanto come il vostro esempio. Quindi se avete un oggetto valido, si ha la risorsa.

Se l'oggetto è costruito, allora si hanno acquisito con successo la risorsa. Ciò significa che per la vita dell'oggetto, è proprio la risorsa. Quando l'oggetto viene eliminato, la risorsa viene rilasciato. Se l'oggetto non viene mai costruito, allora non avete mai acquistato la risorsa. Vedi Wikipedia:

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

Dalla C ++ 2003 Standard 5.3.4 / 17 - Nuovo:

  

Se una parte dell'inizializzazione dell'oggetto sopra descritto termina lanciando una funzione deallocazione adatto eccezione e può essere trovato, la funzione deallocazione è chiamato a liberare la memoria in cui era in costruzione l'oggetto, dopo che l'eccezione continua a propagarsi nel contesto della nuova espressione. Se nessuna funzione di corrispondenza deallocazione univoca può essere trovato, propagare l'eccezione non causa la memoria dell'oggetto per essere liberato. [Nota: Questo è appropriato quando la detta funzione di allocazione non alloca memoria; in caso contrario, è suscettibile di provocare una perdita di memoria. ]

Quindi non può o non può essere una perdita - dipende dal fatto che un deallocatore appropriata può essere trovata (che normalmente è il caso, a meno che operator new / delete sono stato uno scostamento) .Nel caso in cui ci sia un deallocatore adatto, il compilatore è responsabile per il cablaggio in una chiamata ad esso se il costruttore getta.

Si noti che questo è più o meno estranei a ciò che accade a risorse acquisite nel costruttore, che è ciò che il mio primo tentativo di risposta discusso -. Ed è una questione che viene discussa in molte domande frequenti, articoli e messaggi

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top