2010-08-25 24 views
5

La regola generale, solo gli oggetti allocati nel negozio gratuito possono causare perdite di memoria. Ma gli oggetti creati nello stack no.Si considera perdita di memoria?

Ecco il mio dubbio,

int main() 
    { 
     myclass x; 

     ... 

     throw; 

     ... 
    } 

Se tiro non viene gestita, si chiama, terminate(), che a sua volta chiama abort() e si blocca l'applicazione. A questo punto, gli oggetti nello stack non sono vuoti (il distruttore non è invocato).

La mia comprensione è "Quando l'applicazione termina (sia in caso di interruzione che di uscita normale), libera tutta la memoria allocata per l'applicazione". Quindi questo non può essere considerato come perdita di memoria.

Sono corretto?

+0

Dovremmo assumere un'applicazione a thread singolo? –

+3

Otteniamo qualcosa di chiaro, 'throw;' nel tuo codice equivale a 'terminate()', perché stai cercando di rilanciare un'eccezione per la quale non c'è nessuno da rilanciare. È definito dall'implementazione indipendentemente dal fatto che si srotoli lo stack. Se lanci * qualcosa *, tutte le variabili automatiche devono avere chiamato i loro distruttori. Questa è l'idea alla base di SBRM (RAII). – GManNickG

+0

jdv, sì è un'applicazione a thread singolo. – user373215

risposta

5

In un ambiente ospitato (ad esempio il tipico Unix/Windows/Mac OS X, anche DOS, macchina) quando l'applicazione termina tutta la memoria occupata viene automaticamente recuperata dal sistema operativo. Pertanto, non ha senso preoccuparsi di tali perdite di memoria.

In alcuni casi, prima che un'applicazione si interrompa, è possibile che si desideri rilasciare tutta la memoria dinamica allocata per rilevare potenziali perdite di memoria attraverso un rilevatore di perdite, ad esempio valgrind. Tuttavia, anche in questo caso, l'esempio che descrivi non sarebbe considerato una perdita di memoria.

In generale, non riuscire a chiamare un distruttore non equivale a causare una perdita di memoria. Le perdite di memoria derivano dalla memoria allocata sull'heap (con allocatori nuovi o malloc o container). La memoria allocata nello stack viene automaticamente recuperata quando lo stack viene svolto. Tuttavia, se un oggetto contiene un'altra risorsa (ad esempio un file o un handle di finestra), non riuscire a chiamare il suo distruttore chiamerà una perdita di risorse, che può anche essere un problema. Ancora una volta, i sistemi operativi moderni recupereranno le loro risorse quando un'applicazione si interrompe.

+0

Ottima spiegazione. Grazie. – user373215

+0

Spiegazione solida, ma come indicato da Dennis sopra: alcune risorse potrebbero non essere recuperate automaticamente: ad es. segmenti di memoria condivisa, blocchi in esso, file che l'app. normalmente cancellerebbe. –

2

La risposta è, dipende dal sistema operativo. Non riesco a pensare a un sistema operativo moderno che non lo fa in questo modo. Ma i vecchi sistemi (penso di vincere 3.1 in Windows e alcune vecchie piattaforme Linux incorporate) se il programma si chiudeva senza rilasciare le sue richieste di memoria, il sistema operativo li avrebbe mantenuti fino al riavvio.

4

modifica: come accennato da GMan, "throw;" ri-getta un'eccezione generata in precedenza, o se non ce n'è, termina immediatamente. Dal momento che non c'è nessuno in questo caso, la conclusione immediata è il risultato.

La terminazione di un processo pulisce sempre la memoria di qualsiasi spazio utente rimanente in qualsiasi sistema operativo moderno, pertanto non viene in genere considerata una "perdita di memoria", definita come memoria non referenziata non rilasciata in un processo in esecuzione. Tuttavia, dipende dal sistema operativo se una cosa del genere è considerata una "perdita di memoria".

+0

Se in questo caso i distruttori vengono chiamati o meno è definito dall'implementazione, tuttavia si fa una garanzia. (Non sta generando alcuna eccezione.) – GManNickG

+0

Nel mio caso, il distruttore non viene chiamato. Quindi, ho postato la domanda. – user373215

+0

GMan è corretto ... poiché il "lancio" non sta generando alcuna eccezione in questo caso. "gettare;" da solo rigenera un'eccezione generata in precedenza, che non hai. Poiché non c'è un'eccezione generata in precedenza, termina immediatamente. Quindi, se si tratta di una "perdita di memoria", viene quindi definita dal sistema operativo su cui si sta eseguendo. Non ci sono sistemi operativi che conosco che non ripuliscono la memoria di un processo terminato, ma è in questo caso che il sistema operativo previene una perdita di memoria. – samkass

1

Le perdite di memoria sono considerate un problema perché un'applicazione a esecuzione prolungata espelle lentamente la memoria di sistema e potrebbe, nel peggiore dei casi, rendere inutilizzabile l'intera macchina a causa delle condizioni di memoria insufficiente. Nel tuo caso, l'applicazione termina e tutta la memoria allocata all'applicazione verrà restituita al sistema, quindi difficilmente un problema.

+0

Grazie Deus. Buona risposta. – user373215

1

La vera domanda è: "myclass assegna qualsiasi memoria che deve essere libera/cancellata?"

In caso contrario, se l'unica memoria che utilizza è costituita da membri interni, quindi esiste interamente nello stack. Una volta che lascia quella funzione (comunque lo fa), la memoria nello stack viene recuperata e riutilizzata. myclass non c'è più. Questo è solo il modo in cui gli stack funzionano.

Se myclass assegna la memoria che deve essere liberata nel suo dtor, allora siete ancora fortunati, poiché il dtor verrà chiamato mentre lo stack viene svolto durante il lancio. Il dtor sarà già stato chiamato prima che l'eccezione venga dichiarata non gestita e venga terminata la chiamata.

L'unico posto in cui si verificherà un problema è se myclass ha un dtor e il dtor getta come eccezione. Il secondo lancio che si verifica durante lo stack si svolgerà dal primo lancio e terminerà immeditamente senza che vengano chiamati altri.

0

La mia comprensione è "Quando l'applicazione termina (sia in caso di interruzione che di uscita normale), libera tutta la memoria allocata per l'applicazione". Quindi questo non può essere considerato come perdita di memoria.

Sono corretto?

La perdita di memoria è un tipo di errore di programmazione che è leggermente inferiore in scala di errori di programmazione - rispetto all'eccezione non rilevata.

IOW, se il programma non termina correttamente, a.k.a. si blocca, quindi è troppo presto per parlare di perdite di memoria.

In altre note, la maggior parte degli analizzatori di memoria con cui ho lavorato negli ultimi dieci anni non attivava alcun allarme di perdita di memoria nel caso - perché non attivano alcun allarme quando il programma si blocca in modo stupido. Per prima cosa bisogna fare in modo che il programma non si arresti in modo anomalo, per poi eseguire il debug delle perdite di memoria.

1

Da OP,

Se laterale non viene gestita, chiama, terminate(), che a sua volta richiama abort() e si blocca l'applicazione. A questo punto, gli oggetti nello stack non sono vuoti (il distruttore è non invocato).

Questo è un comportamento definito dall'implementazione.

$ 15,3/9- "Se nessun gestore corrispondenza viene trovato in un programma, la funzione terminate() viene chiamato, se o meno lo stack viene svolto prima di questa chiamata di interrompere() è implementazione -definito (15.5.1). "

Quindi, se questo costituisce una perdita di memoria o no è anche un comportamento definito dall'implementazione, immagino.

+0

Grazie Chubsdad. Questa è una buona spiegazione. – user373215