2014-10-16 13 views
6

Questo è qualcosa che lo chiedo per un po 'e non ha mai trovato una risposta per:C++ dimensione di memoria dinamica in fase di esecuzione

Perché è che quando si assegnano qualcosa sul mucchio, non è possibile determinare le dimensioni di esso dal solo puntatore, eppure puoi cancellarlo usando solo il puntatore e in qualche modo C++ sa quanti byte liberare?

Questo ha qualcosa a che fare con il modo in cui è archiviato nell'heap? Questa informazione è presente ma non è esposta dal C++?

E forse questo dovrebbe essere una questione a sé stante, ma penso che sia abbastanza legato quindi mi chiedo qui:

Perché è un array dinamico di elementi deve essere cancellata con delete [] in contrasto con appena il semplice delete comando; perché il C++ ha bisogno di queste informazioni aggiuntive per liberare correttamente tutta la memoria?

+2

http://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array – taocp

+0

Questo è il gestore della memoria del sistema operativo che si occupa di tutto. – dtech

+1

Come per gli array, il compilatore e il runtime C++ hanno accesso "privato" alla lunghezza dell'array per chiamare il numero appropriato di distruttori, se necessario. Anche http://stackoverflow.com/questions/11049144/is-the-size-of-a-dynamically-allocated-array-stored-somewhere/11049350#11049350 – dtech

risposta

5

Quando viene effettuata un'assegnazione, una piccola sezione di memoria immediatamente prima [o, tecnicamente, in un punto completamente diverso, ma poco prima è lo scenario più comune] memorizzerà la dimensione dell'allocazione, e nel caso di new [] anche memorizzare il numero di oggetti assegnati.

Si noti che lo standard C++ non fornisce alcun modo per recuperare queste informazioni per un motivo: potrebbe non descrivere con precisione ciò che viene assegnato, ad esempio la dimensione di un array potrebbe essere arrotondata ad alcune "belle" limite [quasi tutti gli allocatori moderni di circa 16 byte almeno, in modo che la memoria sia utilizzabile per SSE e altre simili implementazioni SIMD su altre architetture di processore]. Quindi, se hai assegnato 40 byte, segnalerebbe 48, che non è quello che hai chiesto, quindi sarebbe piuttosto confuso. E, naturalmente, non vi è alcuna garanzia che le informazioni siano memorizzate su TUTTO - potrebbe essere implicito da qualche altra informazione che è memorizzata nel blocco "admin" dell'assegnazione.

E, naturalmente, è possibile utilizzare il posizionamento new, nel qual caso non esiste un blocco di amministrazione e l'allocazione non viene eliminata nel modo normale - alcuni codici arbitrari non sarebbero in grado di rilevare la differenza.

delete differisce da delete [] dal fatto che delete [] saprà quanti oggetti sono stati assegnati, e chiamare il distruttore per tutti quegli oggetti. È anche possibile [o anche probabile] che new [] memorizzi il numero di elementi in un modo che significa che chiamare delete [] su qualcosa che non è stato creato con new [] andrà terribilmente male.

E come Zan Lynx commentato, che, se non v'è alcun distruttore per gli oggetti (ad esempio quando si assegnano i dati per int o struct { int x; double y; }, ecc - comprese le classi che non hanno un costruttore [nota tuttavia che, se si dispone di un altro classe all'interno della classe, il compilatore costruirà un distruttore per te]), quindi non è necessario memorizzare il conteggio, o fare qualsiasi altra cosa, quindi il compilatore può, se lo desidera, ottimizzare questo tipo di allocazione in regolare new e delete .

+0

'new []' e 'delete []' sono anche ottimizzati per non archiviare mai la lunghezza quando il tipo è POD (plain old data) poiché non deve mai richiamare i distruttori. –

+0

Esattamente quello che volevo sapere. Grazie. :) – Matt