2011-12-16 7 views
6

Si consideri il seguente programma:Quando si fa un oggetto sul mucchio andare fuori del campo di applicazione

int main() { 

    while(...) { 
     int* foobar = new int; 
    } 

    return 0; 
} 

Quando non foobar andare fuori portata?

So che quando si utilizza new, gli attributi sono allocati nello heap e devono essere eliminati manualmente con delete, nel codice sopra, causa una perdita di memoria. Tuttavia, per quanto riguarda la portata?

Ho pensato che sarebbe andato fuori ambito non appena il ciclo while si interrompe, perché non hai più accesso diretto ad esso. Ad esempio, non è possibile eseguire delete dopo la fine del ciclo.

+0

Questo è difficile, perché 'foobar' è un puntatore, che correttamente esce dallo scope e viene distrutto (ma l'oggetto a cui punta è _not_ deallocato). Il 'int' è un oggetto sull'heap, non ha scope e dal momento che non hai la chiamata' delete', è trapelato. –

risposta

13

Fare attenzione qui, foobar è locale al ciclo while, ma l'allocazione nell'heap non ha scope e verrà distrutto solo se si chiama delete su di esso.

La variabile e l'allocazione non sono collegate in alcun modo per quanto riguarda il compilatore. Infatti, l'assegnazione avviene al tempo di esecuzione, quindi il compilatore non lo vede mai.

+3

Raccomando 'std :: unique_ptr ' –

+7

@MooingDuck: mi raccomando 'int' ;-p –

+7

@SteveJessop: Un' int' a giorno tiene il puntatore lontano ... –

2

Il puntatore (foobar) uscirà dall'ambito mentre il programma raggiunge la parentesi di chiusura del ciclo while. Pertanto, se l'espressione in ... rimane true, la memoria verrà persa ogni volta che il ciclo viene eseguito poiché si è perso un handle per l'oggetto assegnato a partire da quella parentesi di chiusura.

+1

si usa 'it' e' quella variabile', senza chiarire neanche. Il puntatore esce dal campo di applicazione, il pointee/oggetto sarà trapelato, perché non ha scopo. –

+0

D: "Quando il foobar esce dal campo di applicazione?", A: "Andrà fuori campo ..." Sto chiaramente parlando di foobar. L'unica variabile in questione è foobar, il pointee/oggetto non è una variabile. Aggiornato a prescindere ... –

+0

Mentre la risposta era corretta, era fuorviante in quanto l'OP chiaramente non distingueva tra il puntatore e il pointee. –

0

Poiché il foobar è dichiarato nel corpo del loop, esso va fuori campo alla fine di ogni iterazione del ciclo. Viene quindi ridichiarato e la nuova memoria viene allocata ancora e ancora fino alla fine del ciclo. L'oggetto reale che il foobar indica non esce mai dall'ambito. L'ambito non si applica agli oggetti allocati dinamicamente (aka heap), solo agli oggetti automatici (stack).

0

foobar esce dallo scope dopo ogni interation del loop.

La memoria allocata e assegnata a foobar viene interrotta, in quanto è ancora allocata nell'heap ma nel programma non sono disponibili riferimenti.

9

foobar è una variabile locale che non rientra nell'ambito alla fine del blocco.

*foobar è un oggetto assegnato dinamicamente con durata manuale. Dal momento che non ha una durata scoped, la domanda non ha senso - non ha un ambito da cui potrebbe andare. La sua durata è gestita manualmente, e l'oggetto è vivo fino a quando non lo hai delete.

La tua domanda è pericolosamente appesantita da pregiudizi e preconcetti. È meglio avvicinarsi al C++ con una mente pulita e un atteggiamento aperto. Solo così sarai in grado di apprezzare al massimo le meraviglie del linguaggio.


Ecco l'approccio pulito e aperto: ci penso 1) classi di memoria (automatico, statico, dinamico), 2) durata degli oggetti (con ambito, permanente, manuali), 3) la semantica degli oggetti (valore (copie) vs riferimento (alias)), 4) RAII e classi di responsabilità singola.Eliminare la mente di un) pila/mucchio, b) puntatori, c) gli operatori new/delete, d) distruttori/costruttori di copia/assegnazione.

+0

Non puoi eliminare completamente la tua mente dagli operatori di assegnamento, perché anche quando ottieni tutto il resto giusto, devi "predefinire" esplicitamente lo spostamento e spostare l'assegnazione per le tue classi di semantica del valore :-) –

+1

+1 per la pulizia e approccio aperto, anche se dovrebbe essere in carattere più grande invece che più piccolo ;-P – AJG85

+1

@SteveJessop: L'ordine permanente è, come sempre: una volta capito perché è possibile ignorare il consiglio, è sicuro ignorare il consiglio :-) (Anche se se non dichiari * nulla *, dovresti ottenere automaticamente la semantica del movimento più ottimale, non?) –

3

Questa è una perdita di memoria piuttosto impressionante. Hai una variabile sullo stack che punta alla memoria allocata nell'heap. È necessario eliminare la memoria sull'heap prima di perdere il riferimento ad esso quando termina l'ambito del ciclo while. In alternativa, se non vuoi preoccuparti della gestione della memoria, usa sempre i puntatori intelligenti per possedere la memoria non elaborata sull'heap e lasciarla pulire.

-2

Foobar Il puntatore viene creato nello stack, ma il nuovo int viene creato nell'heap. Nel caso del ciclo while, ogni volta che il codice si ripete, il foobar cade fuori dall'ambito. Il nuovo int creato persiste sul mucchio. In ogni iterazione viene creato un nuovo int e il puntatore viene reimpostato, il che significa che il puntatore non può più accedere a qualsiasi int (s) precedente nell'heap.

Ciò che sembra mancare, in ognuna delle risposte precedenti, e anche in questo caso, è il mucchio che non rientra nel campo di applicazione. Forse, sto ottenendo la terminologia errata, ma so che a un certo punto anche l'heap viene resettato. Può verificarsi quando il programma non viene più eseguito o quando il computer è spento, ma so che si verifica.

Diamo un'occhiata a questa domanda da una prospettiva diversa. Ho scritto un numero qualsiasi di programmi, che perdono memoria. Nel corso degli anni, ho posseduto il mio computer, sono positivo, ho perso oltre 2 gigabyte di memoria. Il mio computer ha solo 1 gig di memoria. Pertanto, se l'heap non rientra MAI al di fuori dell'ambito, il mio computer ha una memoria magica. Uno di voi si preoccuperebbe di spiegare quando esattamente l'heap cade dal campo di applicazione?

1

Qui foobar è un puntatore int che occupa memoria nello stack. L'istanza int che si sta creando dinamicamente con new passa all'heap. Quando foobar esce dall'ambito, si perde il riferimento ad esso, quindi non è possibile eliminare la memoria allocata nell'heap.

La soluzione migliore sarebbe:

while(--) 
{ 
    int foobar; 
}//it goes out of scope here. deleted from stack automatically!! 

Se si desidera continuare a utilizzare l'allocazione dinamica quindi fare questo:

while(--) 
{ 
    int* foobar=new int; 
    //do your work here! 
    delete foobar; //This deletes the heap memory allocated! 
    foobar=NULL; //avoid dangling pointer! :) 
} 
Problemi correlati