2012-01-30 10 views
5

Si osserva la differente dimensione della allocazione di memoria durante la creazione oggetto su classe C sotto,allocazione di memoria sulla creazione oggetto C++

class C { 
int i; 
int j; 
}; 

void f() { 
C *c = new C; 
C *c2 = new C[2]; 
C (*c3)[2] = new C[2][2]; 
} 

c è allocato con 8 byte;

c2 è assegnato con 8 * 2 + 4 byte;

c3 è allocato con 8 * 2 * 2 + 4 byte.

Perché c2 e c3 acquisiscono altri 4 byte?

+5

Si tratta di una questione compiti a casa? – templatetypedef

+1

è un po 'il mio compito. :) – sof

+0

Come stai misurando la quantità di memoria allocata? –

risposta

8

ricordi che C++ separa allocazione di memoria e oggetto espressione. La nuova matrice predefinita T * p = new T[N]; alloca memoria sufficiente per gli oggetti Ne crea tali oggetti. All'altra estremità, delete[] p; deve chiamare il distruttore di tutti quegli elementi e quindi liberare la memoria.

Mentre allocare e liberare memoria viene gestito dalla piattaforma e la memoria libera è sufficientemente identificata nel sistema operativo da un singolo valore di puntatore, la costruzione e la distruzione di oggetti è più complicata. Il numero di oggetti reali deve essere memorizzato da qualche parte e, a tale scopo, lo standard consente un'implementazione C++ per richiedere più memoria di N * sizeof(T). È vero che il puntatore p punterà sempre l'inizio della matrice di N oggetti, ma p non deve essere lo stesso puntatore che è stato restituito dal allocatore di memoria sottostante. (Infatti, è garantito che p sia esattamente il valore del risultato dell'allocazione sottostante compensato dalla quantità di memoria in eccesso.)

I dettagli sono interamente lasciati alla realizzazione.Alcune piattaforme forniscono tuttavia garanzie aggiuntive; per esempio, la Itanium ABI (che chiama l'extra di dati "allineamento cookie") dice che la memoria dei new T[N] verrà presentata come segue:

+- alignof(T) --+-- sizeof(T) --+-- sizeof(T) --+-- sizeof(T) --+-- ... 
| ***** [8B: N] | 1st element | 2nd element | 3rd element | ..... 
+---------------+---------------+---------------+---------------+-- ... 
A    A 
|    |_ result of "new T[N]" 
| 
|_ value returned "operator new[]()" 
+0

Thx per le informazioni dettagliate. Ho appena capito che la piattaforma a 32 bit usa questi 32/8 = 4 byte aggiuntivi per memorizzare la dimensione totale degli oggetti allocati con l'espressione 'new []'. – sof

+0

@Kerrek, e cosa succede se ho un overload 'operatore new [] (size_t n)' - c'è qualche garanzia che 'new C [2]' darebbe 'n' che è esattamente 2 * sizeof (C)? – Andrey

+0

@Andrey: no no, questo non è correlato. Qualsiasi operatore della nuova serie che finisce per essere chiamato verrà chiamato con un argomento di dimensione che include il requisito di spazio aggiuntivo. –

4

Dalla standard (sezione [expr.mew]):

A nuova espressione passa la quantità di spazio richiesto per la funzione di assegnazione come primo argomento di tipo std::size_t. Tale argomento non deve essere inferiore alla dimensione dell'oggetto che si sta creando; potrebbe essere maggiore della dimensione dell'oggetto che si sta creando solo se l'oggetto è un array.

Chiaramente lo standard prevede che alcune informazioni aggiuntive vengano memorizzate con una matrice allocata dinamicamente.

Ora, utilizzare il debugger per vedere cosa sta insaccato in quei byte in più, e capire quando questa informazione in più potrebbe essere necessaria per il compilatore a fare il suo lavoro.

(Suggerimento: riparare il vostro programma in modo che non ci siano perdite di memoria)

3

Un sacco di compilatori utilizzare i 4 byte prima che il puntatore restituito dal nuovo [] per memorizzare il numero di oggetti effettivamente assegnati. Questo è tutto dipende dall'implementazione ed è importante ricordare che l'aritmetica dei puntatori che porta fuori della gamma di memoria allocata risultati comportamento indefinito