2015-09-10 11 views
6

Capisco che, quando scriviamo delete [] su un puntatore creato da un corrispondente new [], il programma cercherà le informazioni contabili sull'array e scoprirà la dimensione dell'elemento dell'array (un contatore). Quindi il programma invoca il distruttore dell'elemento su ognuno di essi. Finalmente la memoria (che memoria ??) è deallocata da una funzione denominata operator delete.Cancella [] deallocare la memoria in un colpo dopo aver richiamato i distruttori?

Quello che chiedo è se delete[] sarà deallocare la intera memoria, assegnato dal new[] espressione, in un solo colpo perché tali informazioni (quantità totale di memoria) è disponibile dopo tutti gli elementi vengono distrutti, o sarà in successione deallocare la memoria occupata dagli elementi della matrice su cui ha richiamato i distruttori su?

Un correlata quesion follow-up è chiesto Does delete (non array form) know the total amount of memory allocated by either new or new[]

+2

Avrei pensato che la risposta alla tua domanda dipendesse dall'implementazione dal compilatore e dal sistema operativo –

+3

"libero" ha bisogno di conoscere la dimensione dell'allocazione restituita da 'malloc'? –

+2

Lo standard C++ dice qualcosa sul presunto comportamento delle espressioni 'delete'? – Rich

risposta

2

Tutta la memoria verrà rilasciata nell'allocatore sottostante in una volta. Questo è richiesto dallo standard C++, sebbene non sia particolarmente chiaro. N3337 è l'approssimazione più vicina allo standard ufficiale C++ 11 disponibile online gratuitamente. Esaminare la sezione 5.3.5, [expr.delete], che specifica il codice a cui si espande l'invocazione di delete[].In particolare, operator delete[] viene chiamato una volta nel passaggio 7, dopo i distruttori sono stati richiamati per tutti gli elementi dell'array (passaggio 6).

Si può anche dedurre questo comportamento dalla formulazione in 18.6.1.2 [new.delete.array] Per quanto riguarda ciò che i puntatori sono validi per passare a operator delete[]:" ... è il valore restituito da una precedente chiamata a operator new[] (... avvertimenti ...) ". Poiché operator new[] restituisce un puntatore a un intero array, operator delete[] deve essere invocato una volta per un intero array.

1

5.3.5/2:

Nella prima alternativa (cancella oggetto), il valore dell'operando di eliminare può essere nullo valore del puntatore, un puntatore a un oggetto non-array creato da una nuova espressione precedente o un puntatore a un subobject (1.8) che rappresenta una classe base di tale oggetto (clausola 10). In caso contrario, il comportamento non è definito.

Questo ci mostra chiaramente che il comportamento nella vostra situazione proposto non è definito dalla norma, che lascia "che non perda la memoria" o "perdite di memoria", come i due comportamenti indefiniti più probabili (sembra che la corruzione heap potrebbe essere una terza possibilità molto meno probabile solo per completezza). Basta non scrivere questo codice e si evitano possibili problemi.

0

In pratica il vostro esempio

auto pi = new int[10]; 
... 
delete pi; 

funziona bene ed è abbastanza comune nei programmi di lavoro. Mi fiderò di quelli che l'hanno cercato nello standard, che è un comportamento indefinito. Quindi non ti suggerirò di sfruttare il fatto che funziona regolarmente. In pratica, l'allocatore tiene traccia delle dimensioni totali e la deallocazione libera la dimensione totale corretta, quindi l'associazione di nuovo [] con delete fa sì che i distruttori degli elementi oltre lo zero non vengano chiamati e non fa danno per gli array di oggetti con distruzione banale. Ma codificare un comportamento indefinito non è una grande idea anche quando sei sicuro che ogni compilatore si comporta bene per quel particolare UB.

Edit: ora che è stato rimosso tutto ciò che dalla domanda da fare solo la parte più banali della domanda iniziale:

presumo lo standard non va in alcun modo così dettagliato, in modo da un'implementazione potrebbe fare neanche. Ma sono anche sicuro che qualsiasi implementazione reale libera l'intero blocco contiguo in un colpo solo dopo aver chiamato tutti i distruttori. (L'implementazione non avrebbe altra scelta se non quella di farlo in modo corretto per i casi in cui delete [] è sovrascritto)

+0

Il seguente -up domanda viene spostata su http://stackoverflow.com/questions/32508952/does-delete-non-array-form-know-the-total-amount-of-memory-allocated-by-either – Rich