2009-03-24 7 views
34

Nella mia funzione C++ main, ad esempio, se avessi un puntatore a una variabile che utilizza la memoria heap (anziché la memoria di stack), questo viene automaticamente rilasciato dopo che l'applicazione è stata chiusa? Assumerei così.C'è un motivo per chiamare delete in C++ quando un programma sta per uscire comunque?

Anche così, è buona prassi eliminare sempre le allocazioni dell'heap anche se si pensa che non verranno mai utilizzate in una situazione in cui la memoria viene automaticamente rilasciata all'uscita?

Ad esempio, c'è qualche punto in questo?

int main(...) 
{ 
    A* a = new A(); 
    a->DoSomething(); 
    delete a; 
    return 0; 
} 

Stavo pensando forse nel caso mi refactoring (o qualcuno refactors altro) che il codice e lo mette in nessun'altra parte dell'applicazione, dove delete è davvero neccecary.

Così come la risposta di Brian R. Bondy (che parla in modo specifico delle implicazioni in C++), Paul Tomblin ha anche un good answer to a C specific question, che parla anche del distruttore C++.

+0

Il duplicato menzionato è su C, che manca alcune importanti informazioni sul distruttore che è un problema in C++. –

+0

@Brian, la mia risposta al duplicato menziona anche i distruttori (ora). La mia sensazione che questo dovrebbe essere cancellato è ancora valida. –

+0

Non sai cosa intendi per distruttore - per favore chiarisci. –

risposta

61

È importante chiamare esplicitamente delete perché è possibile che il distruttore che si desidera eseguire sia un codice. Come forse scrivere alcuni dati in un file di registro. Se lasci che il sistema operativo liberi la tua memoria per te, il tuo codice nel distruttore non verrà eseguito.

La maggior parte dei sistemi operativi rilascia la memoria quando il programma termina. Ma è una buona pratica deallocarlo da soli e come ho detto sopra il sistema operativo non chiamerà il tuo distruttore.

Come per la chiamata di eliminazione in generale, sì si desidera sempre chiamare Elimina, altrimenti si avrà una perdita di memoria nel programma, che porterà a nuove allocazioni non riuscite.

+9

Non dimenticare che un membro della classe può anche tenere qualcosa che non scompare automaticamente alla fine del programma, come un socket o una connessione o qualcosa del genere. La memoria non è l'unica cosa che perde e non tutte le perdite possono essere ripulite automaticamente. –

+0

Cosa succede se ho assegnato memoria per Tree (in particolare trie), e all'interno di destructor, tutto quello che devo fare è 'delete'. Devo ancora chiamare esplicitamente delete? o fare affidamento sul sistema operativo per fare per me? –

6

Pensa alla tua classe A che deve essere distrutta.
Se non si chiama delete su a, il distruttore non verrà chiamato. Di solito, non importa se il processo finisce comunque. Ma cosa succede se il distruttore deve rilasciare, ad es. oggetti in un database? Svuota una cache in un file di log? Scrivi una cache di memoria sul disco?

Si vede, non è solo "buona pratica" per eliminare oggetti, in alcune situazioni è necessario.

7

Considerare il caso in cui l'oggetto da eliminare ha acquisito una risorsa esterna che non può essere liberata in modo sicuro dal sistema operativo. Se non si chiama delete su quell'oggetto, si ha una vera perdita.

2

assicurati sempre di eliminarlo da solo. Un sistema operativo si prenderà cura di questo, ma per escludere bug che possono essere facilmente evitati

21

Sì, aiuta ad eliminare i falsi positivi quando si esegue il programma tramite uno strumento di rilevamento perdite di memoria.

+1

Per favore, potresti indicarmi la direzione di alcuni buoni strumenti di rilevamento delle perdite? –

+1

Su Windows, BoundChecker di Compuware è eccellente, ma costoso. Su Linux, ho sentito cose positive su Valgrind, ma non l'ho ancora provato. – Ferruccio

+2

Uno gratuito per MSVC++ è Visual Leak Detector (esegui una ricerca su Internet - lo troverai facilmente) –

3

Un altro motivo per eliminare esplicitamente gli oggetti è che se l'applicazione presenta una perdita di memoria reale, diventa più facile utilizzare strumenti come valgrind per trovare le perdite se non è necessario setacciare "perdite" che provengono da non disturbare pulire.

3

Un altro motivo per eliminare è quello di evitare falsi allarmi da un rilevatore di perdite che è possibile utilizzare in futuro. Se hai falsi allarmi, potresti non prestare attenzione a una vera perdita segnalata da un rilevatore di perdite: sarà sepolto tra i falsi nel rapporto.

+1

Per essere giusti, dato il codice dell'OP, questi non sarebbero allarmi "falsi";) –

9

Sì.

  • La norma non fa garanzia che il sistema operativo sarà ripulire la memoria. Puoi aspettarti questo sulle piattaforme mainstream, ma perché cogli l'occasione?
  • Si minimizza il disordine riportato da strumenti come valgrind se non si perde deliberatamente memoria.
  • Se prendi questa abitudine, chi dirà che un giorno non applicheresti accidentalmente questo approccio da qualche parte?
  • necessario distruzione degli oggetti. Di solito presumo solo che tu lo faccia. Non ti fa male.
+1

Il punto # 3 è il più convincente per me. È meno difficile eliminare sempre le allocazioni piuttosto che provare e decidere sempre quando è appropriato. Mi ricorda di usare gli indicatori di direzione delle auto - mi sono sempre chiesto perché le persone si sono preoccupate di usarlo * a volte *; è meglio che diventi un'abitudine in cui non devi pensarci affatto. – tenfour

+0

@tenfour: Infatti. Se non puoi garantire che l'auto di fronte a te indichi sempre quando è appropriato, allora non puoi _ever_ essere sicuro quando non sta girando. L'intero sistema si rompe. –

+0

@LightnessRacesinOrbit: +1 per aver detto che "Lo standard non garantisce che il sistema operativo ripulirà la memoria.". Mi piace anche il tuo terzo punto. – Destructor

Problemi correlati