2015-04-17 18 views
5

Che cosa succede quando faccio qualcosa comeUtilizzando "nuove" più volte sullo stesso puntatore

int * ptr = new int; 
    *ptr = 5; 
    // ... do some stuff here 
    ptr = new int; 
    // ... reuse ptr to do some other stuff 

al contrario di

int * ptr1 = new int; 
    *ptr1 = 5; 
    // ... do some stuff here 
    delete ptr1; 
    int * ptr2 = new int; 
    // ... use ptr2 now 

????

La stessa cosa accade a livello hardware? In altre parole, nel primo caso, ptr = new int; si sposta dalla precedente coppia puntatore/valore e cosa succede a quei vecchi valori? Vengono rimpiazzati, galleggiano da qualche parte, ecc.?

+3

Se non si chiama "cancella", si ottiene una perdita di memoria (1 int). Utilizza gli idiomi C++ e std :: unique_ptr o std :: shared_ptr , quindi la memoria verrà rilasciata automaticamente. – Robinson

+0

Il primo esempio rilascia solo memoria. La memoria allocata per la prima chiamata a 'new' è persa –

+0

@CharlesSalvia Ma cosa succede quando è" perso "? Che cosa succede al mio sistema operativo? –

risposta

9

tuo int *ptr è solo una variabile che memorizza un indirizzo, niente di più.

Dopo il primo int * ptr = new int;, contiene l'indirizzo su un numero intero allocato dinamicamente. Dopo il secondo int * ptr = new int;, contiene l'indirizzo un altro numero intero allocato dinamicamente.

Quello che succede allora non è niente di speciale, l'unica cosa è che non hai chiamato delete così la memoria allocata per il primo intero non sarà mai liberata. Non c'è nulla da tenere traccia di esso, il suo indirizzo non è memorizzato da nessuna parte, e così continuerà a essere spazio assegnato inutile fino alla fine del programma.

+0

"fino alla fine del programma" - si presume che si stia utilizzando un sistema operativo in cui terminare un processo consente di recuperare tutta la sua allocazione dall'OS –

+0

Tutti i principali sistemi operativi post 2000, penso che – coyotte508

+1

un controesempio moderno sarebbe un Windows DLL: può essere caricata e scaricata un numero arbitrario di volte da un processo, quindi se il tuo codice perde memoria allora questo può accumularsi nel tempo (se il processo non finisce mai, non c'è un heap separato per la DLL, quindi la memoria non può essere reclamato). –

7

Nel primo esempio, il puntatore viene sovrascritto, ma l'oggetto a cui è indirizzato esiste ancora ed è "mobile" da qualche parte. Ciò causa memory leaking.

Se ciò accade in una funzione utilizzata di frequente o in un ciclo, è possibile esaurire facilmente la memoria, memorizzando valori a cui non è possibile accedere o che non potranno più accedervi.

La perdita è in effetti un errore molto comune. A good practice è di evitarlo usando puntatori intelligenti come shared_ptr. Questi tengono traccia di un conteggio dell'utilizzo e liberano automaticamente l'oggetto se non viene più utilizzato. Per esempio:

shared_ptr<int> ptr = make_shared<int>(); // allocate an int 
*ptr = 5; 
// ... do some stuff here 
ptr = make_shared<int>(); // the old object is no longer used so deleted automatically 
// ... reuse ptr to do some other stuff  
+0

Funzionerebbe anche quando si usano std :: unique_ptrs e std :: make_unique? O il riferimento conta un requisito affinché funzioni? –

+0

@AdrianKoch questo ovviamente funziona anche con [unique_ptr] (http://en.cppreference.com/w/cpp/memory/unique_ptr). La differenza è che non è possibile copiare un unique_ptr – Christophe

+0

Ok, buono a sapersi. –

Problemi correlati