Come potrebbe l'associazione nuovo [] con eliminazione eventualmente portare ad unica perdita di memoria?

StackOverflow https://stackoverflow.com/questions/1913343

Domanda

Innanzitutto, utilizzando delete nulla allocato con new[] è un comportamento definito secondo lo standard C ++.

In Visual C ++ 7 tale abbinamento può portare a una delle due conseguenze.

Se il tipo di nuova [] 'ed ha costruttore banale e distruttore VC ++ usa semplicemente new invece di new[] e l'utilizzo di delete per quel blocco funziona bene -. new chiama semplicemente 'allocare memoria', delete chiama semplicemente 'memoria libera'

Se il tipo di nuova [] 'ed ha un costruttore non banale o distruttore il trucco di cui sopra non può essere fatto - VC ++ 7 deve richiamare esattamente il giusto numero di distruttori. Così antepone la matrice con un size_t memorizzare il numero di elementi. Ora l'indirizzo restituito da punti new[] sul primo elemento, non è sopra l'inizio del blocco. Quindi, se si utilizza delete chiama solo il distruttore per il primo elemento e le chiamate "memoria libero" con l'indirizzo diverso da quello restituito da "allocare memoria" e questo porta a qualche visualizzazione iniziale errore all'interno HeapFree () che sospetto riferisce a danneggiamento di heap.

Tuttavia ogni qua e là si può leggere false dichiarazioni che l'utilizzo di delete dopo new[] porta ad una perdita di memoria. Ho il sospetto che la dimensione nulla di corruzione heap è molto più importante di un dato di fatto che il distruttore è chiamato per il primo elemento solo e, eventualmente, i distruttori non chiama non ha libero sub-oggetti heap allocata.

Come potrebbe utilizzare delete dopo new[] forse solo portare ad una perdita di memoria su alcuni implementazione C ++?

È stato utile?

Soluzione

Supponiamo che io sono un compilatore C ++ e implemento la mia gestione della memoria in questo modo: io anteporre ogni blocco di memoria riservato con la dimensione della memoria, in byte. Qualcosa di simile a questo:

| size | data ... |
         ^
         pointer returned by new and new[]

Si noti che, in termini di allocazione di memoria, non c'è differenza tra new e new[]:. Entrambi solo allocare un blocco di memoria di una certa dimensione

Ora, come si delete[] conosce la dimensione della matrice, al fine di chiamare il giusto numero di distruttori? È sufficiente dividere la size del blocco di memoria da sizeof(T), dove T è il tipo di elementi della matrice.

Ora supponiamo che io implementare delete semplicemente come una chiamata al distruttore, seguita dalla liberazione dei byte size, quindi non saranno mai chiamati i distruttori degli elementi successivi. Ciò si traduce in perdite risorse assegnate dagli elementi successivi. Eppure, a causa I faccio bytes free size (non sizeof(T) byte), nessun danneggiamento di heap si verifica.

Altri suggerimenti

La fiaba di mescolare new[] e delete presumibilmente causando una perdita di memoria è proprio questo: una favola. Essa non ha assolutamente alcun piano nella realtà. Non so da dove venisse, ma ormai acquisito una vita propria e sopravvive come un virus, moltiplicazione dalla parola di bocca da un principiante ad un altro.

La più probabile logica dietro questa dialogo "perdita di memoria" è che dal punto innocentemente ingenuo di vista della differenza tra delete e delete[] è che delete viene utilizzato per distruggere un solo oggetto, mentre delete[] distrugge un array di oggetti ( "molti "oggetti). Una conclusione naive che di solito è derivato da questo è che il primo elemento della matrice sarà distrutto da delete, mentre il resto persisterà, creando così la presunta "perdita di memoria". Naturalmente, qualsiasi programmatore con almeno conoscenza di base di implementazioni tipiche mucchio avrebbe capito subito che il più probabile conseguenza di ciò è danneggiamento di heap, non una "perdita di memoria".

Un'altra spiegazione popolare per la teoria ingenua "perdita di memoria" è che, poiché il numero sbagliato di distruttori viene chiamato, la memoria secondaria di proprietà degli oggetti nella matrice non ottiene deallocato. Questo potrebbe essere vero, ma è ovviamente una spiegazione molto forzato, che porta poca rilevanza a fronte di problema molto più grave di corruzione heap.

In breve, mescolando diverse funzioni di assegnazione è uno di quelli errori che portano a solido, imprevedibile e molto pratico comportamento indefinito . Qualsiasi tentativo di imporre alcuni limiti concreti sulle manifestazioni di questo comportamento non definito sono solo spreco di tempo e sicuro segno della mancanza di conoscenza di base.

Inutile aggiungere, new/delete e new[]/delete[] sono infatti due meccanismi di gestione della memoria indipendenti, che sono indipendentemente personalizzabili. Una volta che ottengono personalizzati (sostituendo le funzioni di gestione della memoria prime) non c'è assolutamente alcun modo per cominciare a prevedere ciò che potrebbe accadere se ottengono misti.

La tua domanda è in realtà "perché danneggiamento di heap non succede?". La risposta a questa è "perché il gestore mucchio registra blocchi di dimensioni assegnate". Torniamo a C per un minuto: se si desidera assegnare un singolo int in C si farebbe int* p = malloc(sizeof(int)), se si vuole allocare array di dimensione n è possibile scrivere o int* p = malloc(n*sizeof(int)) int* p = calloc(n, sizeof(int)). Ma in ogni caso si liberarlo da free(p), non importa come si è assegnato. Non si può mai passare dimensioni a free (), free () solo "sa" quanto a liberare, perché la dimensione di una malloc () - blocco ed è salvato da qualche parte "di fronte" del blocco. Torna a C ++, nuovi / cancellare e new [] / delete [] sono generalmente implementati in termini di malloc (anche se non devono essere, non si deve fare affidamento su questo). Questo è il motivo per cui nuovo [] / delete combinazione non danneggiare l'heap -. Elimina libererà la giusta quantità di memoria, ma, come spiegato da tutti prima di me, è possibile ottenere le perdite non chiamando il giusto numero di distruttori

Detto questo, il ragionamento sul comportamento definito in C ++ è sempre inutile esercizio. Perché è importante se nuova combinazione [] / delete capita di lavorare, "solo" perdite o danneggiamento di heap provoca? Non si deve codificare così, punto e basta! E, in pratica, vorrei evitare gestione manuale della memoria, quando possibile -. STL e spinta sono lì per un motivo

Se il distruttore non banale che non sono chiamati per tutti, ma il primo elemento della matrice si suppone per liberare la memoria si ottiene una perdita di memoria, come questi oggetti non vengono puliti correttamente.

E 'porterà ad una perdita in tutte le implementazioni di C ++, in ogni caso in cui il distruttore libera la memoria, perché il distruttore non viene mai chiamato.

In alcuni casi può causare errori di molto peggio.

perdita di memoria potrebbe accadere se nuovo operatore () viene sostituito, ma nuovo [] non è. stesso discorso vale per la cancellazione / delete operatore []

Oltre conseguente comportamento indefinito, la causa più diretto di perdite risiede nella attuazione non chiamare il distruttore per tutto il primo oggetto dell'array. Ciò, ovviamente, causare perdite se gli oggetti hanno stanziato risorse.

Questa è la classe più semplice possibile che riuscivo a pensare con conseguente questo comportamento:

 struct A { 
       char* ch;
       A(): ch( new char ){}
       ~A(){ delete ch; }
    };

A* as = new A[10]; // ten times the A::ch pointer is allocated

delete as; // only one of the A::ch pointers is freed.

PS: notare che i costruttori non riescono a ottenere chiamato in un sacco di altri errori di programmazione, anche: i distruttori della classe base non virtuali, falso ricorso a puntatori intelligenti, ...

In ritardo per una risposta, ma ...

Se il meccanismo di eliminazione è semplicemente quello di chiamare il distruttore e posizionare il puntatore liberato, insieme con la dimensione implicita sizeof , su una pila libera, quindi chiamando delete su un pezzo di memoria allocata con il nuovo [] si tradurrà memoria sta perdendo - ma non la corruzione. Più sofisticate strutture malloc potrebbe corrompere il, o rilevare, questo comportamento.

Perché la risposta non può essere che esso provoca sia?

Ovviamente la memoria è trapelato se si verifica danneggiamento di heap o meno.

O meglio, dato che posso re-implementare new e delete ..... non può non causare nulla. Tecnicamente posso causare new e delete per eseguire new [] e delete [].

di qui. Non definito Comportamento

stavo rispondendo a una domanda che è stata delimitata come duplicato, quindi mi limiterò a copiare qui nel caso in cui Metters. E 'stato detto ben prima di me le opere di allocazione di memoria modo, `ll solo spiegare la causa e gli effetti.

Solo una piccola cosa giusta fuori google: http: //en.cppreference. com / w / cpp / memoria / new / operator_delete

In ogni caso, Elimina è una funzione per un singolo oggetto. E 'libera l'istanza dal puntatore, e lascia;

delete [] è una funzione utilizzata al fine di rilasciare le matrici. Ciò significa che, doesnt solo liberare il puntatore; Dichiara l'intero blocco di memoria di detta matrice come rifiuti.

Questo è tutto fresco, in pratica, ma mi dite il vostro funzionamento dell'applicazione. Probabilmente ti starai chiedendo ... perché?

La soluzione è C ++ non risolve perdite di memoria . Se si `ll utilizzare eliminare senza le parenthesises, sarà eliminare solo l'array come un oggetto -. Un proccess, che potrebbe causare un perdita di memoria

storia fresca, perdita di memoria, perché dovrei preoccuparmi?

Perdita di memoria si verifica quando la memoria allocata non viene cancellato. Quel ricordo richiede quindi inutile spazio su disco, che vi farà perdere la memoria utile per praticamente senza motivo. Questo è male programmazione, e probabilmente si dovrebbe risolvere il problema nei vostri sistemi.

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