free Cosa succede VERAMENTE quando non si libera dopo malloc?



8 Answers

Sì, hai ragione, il tuo esempio non fa alcun danno (almeno non sulla maggior parte dei sistemi operativi moderni). Tutta la memoria allocata dal processo verrà ripristinata dal sistema operativo una volta che il processo è terminato.

Fonte: Allocation e GC Myths (avviso PostScript!)

Assegnazione Mito 4: i programmi non-garbage-raccolti dovrebbero sempre deallocare tutta la memoria che allocano.

La verità: i deallocations omessi nel codice di esecuzione frequente causano perdite crescenti. Raramente sono accettabili. ma i programmi che conservano la maggior parte della memoria allocata fino all'uscita del programma spesso funzionano meglio senza alcuna deallocazione interveniente. Malloc è molto più facile da implementare se non è disponibile.

Nella maggior parte dei casi, deallocare la memoria appena prima dell'uscita del programma è inutile. Il sistema operativo lo reclamerà comunque. Il tocco gratuito e la pagina negli oggetti morti; il sistema operativo no.

Conseguenza: fai attenzione ai "rilevatori di perdite" che contano le allocazioni. Alcune "perdite" sono buone!

Detto questo, dovresti davvero cercare di evitare tutte le perdite di memoria!

Seconda domanda: il tuo design è ok. Se è necessario memorizzare qualcosa fino alla chiusura dell'applicazione, è possibile farlo con allocazione dinamica della memoria. Se non si conosce la dimensione richiesta in anticipo, non è possibile utilizzare la memoria allocata staticamente.

c malloc free

Questo è stato qualcosa che mi ha infastidito per secoli.

A scuola ci insegnano tutti (almeno, io ero) che DEVI liberare ogni puntatore che viene assegnato. Sono un po 'curioso, però, del costo reale di non liberare memoria. In alcuni casi ovvi, come quando malloc viene chiamato all'interno di un ciclo o parte di un'esecuzione di thread, è molto importante liberare così non ci sono perdite di memoria. Ma considera i seguenti due esempi:

Innanzitutto, se ho codice è qualcosa del genere:

int main()
{
    char *a = malloc(1024);
    /* Do some arbitrary stuff with 'a' (no alloc functions) */
    return 0;
}

Qual è il vero risultato qui? Il mio pensiero è che il processo muoia e quindi lo spazio dell'heap è sparito comunque, quindi non c'è nulla di male nel perdere la chiamata a free (tuttavia, riconosco l'importanza di averlo comunque per la chiusura, la manutenibilità e le buone pratiche). Ho ragione in questo pensiero?

In secondo luogo, diciamo che ho un programma che agisce un po 'come una shell. Gli utenti possono dichiarare variabili come aaa = 123 e quelle sono memorizzate in una struttura di dati dinamica per un uso successivo. Chiaramente, sembra ovvio che tu usi una soluzione che chiamerà alcune funzioni di allocazione (hashmap, lista collegata, qualcosa del genere). Per questo tipo di programma, non ha senso liberarsi mai dopo aver chiamato malloc perché queste variabili devono essere presenti in ogni momento durante l'esecuzione del programma e non c'è un buon modo (che io possa vedere) per implementarlo con spazio allocato staticamente. È un cattivo progetto avere un mucchio di memoria che viene assegnato, ma solo liberato come parte del processo che termina? Se è così, qual è l'alternativa?




Hai ragione, nessun danno è fatto ed è più veloce uscire

Ci sono diverse ragioni per questo:

  • Tutti gli ambienti desktop e server rilasciano semplicemente l'intero spazio di memoria su exit (). Non sono consapevoli delle strutture di dati interne al programma come gli heap.

  • Quasi tutte le implementazioni free() non restituiscono mai comunque memoria al sistema operativo.

  • Ancora più importante, è una perdita di tempo quando viene eseguita prima dell'uscita (). All'uscita, vengono semplicemente rilasciate le pagine di memoria e lo spazio di swap. Al contrario, una serie di chiamate gratuite () brucerà il tempo della CPU e può comportare operazioni di paging del disco, mancate cache e sfratti della cache.

Per quanto riguarda la possibilità del futuro riutilizzo del codice che giustifica la certezza delle operazioni inutili: questa è una considerazione, ma non è probabilmente la modalità Agile . YAGNI!




Sono completamente in disaccordo con tutti coloro che dicono che OP è corretto o che non ci sono danni.

Tutti parlano di sistemi operativi moderni e / o legacy.

Ma cosa succede se sono in un ambiente in cui semplicemente non ho un sistema operativo? Dove non c'è niente?

Immagina ora che tu stia usando interrupt con stile thread e allochi memoria. Nello standard ISO / IEC C: 9899 è la durata della memoria indicata come:

7.20.3 Funzioni di gestione della memoria

1 L'ordine e la contiguità della memoria allocata da chiamate successive alle funzioni calloc, malloc e realloc non sono specificate. Il puntatore restituito se l'allocazione ha esito positivo è opportunamente allineato in modo che possa essere assegnato a un puntatore a qualsiasi tipo di oggetto e quindi utilizzato per accedere a tale oggetto o una matrice di tali oggetti nello spazio allocato (finché lo spazio non viene esplicitamente deallocato) . La durata di un oggetto assegnato si estende dall'allocazione fino alla deallocazione. [...]

Quindi non deve essere dato che l'ambiente sta facendo il lavoro di liberazione per te. Altrimenti verrebbe aggiunto all'ultima frase: "O fino a quando il programma non termina".

Quindi, in altre parole: non liberare la memoria non è solo una cattiva pratica. Produce codice non portatile e non conforme alla C. Che può almeno essere visto come 'corretto, se il seguente: [...], è supportato dall'ambiente'.

Ma nei casi in cui non hai affatto OS, nessuno sta facendo il lavoro per te (so che generalmente non assegni e rialloca la memoria su sistemi embedded, ma ci sono casi in cui potresti volerlo fare.)

Quindi, parlando in generale, C (come l'OP viene etichettato), si tratta semplicemente di produrre codice errato e non portabile.




Se stai usando la memoria che hai allocato, allora non stai facendo nulla di sbagliato. Diventa un problema quando si scrivono funzioni (diverse da main) che allocano memoria senza liberarla e senza renderla disponibile per il resto del programma. Quindi il tuo programma continua a funzionare con quella memoria assegnata ad esso, ma non c'è modo di usarlo. Il tuo programma e altri programmi in esecuzione sono privati ​​di quella memoria.

Modifica: Non è preciso al 100% che altri programmi in esecuzione siano privi di quella memoria. Il sistema operativo può sempre consentirgli di usarlo a scapito dello swapping del programma nella memoria virtuale ( </handwaving> ). Il punto è, però, che se il tuo programma libera memoria che non sta usando, allora è meno probabile che uno scambio di memoria virtuale sia necessario.




Qual è il vero risultato qui?

Il tuo programma ha fatto trapelare la memoria. A seconda del sistema operativo, potrebbe essere stato ripristinato.

La maggior parte dei moderni sistemi operativi desktop recupera la perdita di memoria alla fine del processo, rendendo tristemente comune ignorare il problema, come si può vedere da molte altre risposte qui.)

Ma ti stai affidando a una funzione di sicurezza su cui non dovresti fare affidamento e il tuo programma (o funzione) potrebbe essere eseguito su un sistema in cui questo comportamento si traduce in una perdita di memoria "dura", la prossima volta.

Si potrebbe essere in esecuzione in modalità kernel, o su sistemi operativi vintage / embedded che non impiegano la protezione della memoria come compromesso. (Gli MMU occupano spazio vuoto, la protezione della memoria costa più cicli della CPU, e non è troppo chiedere a un programmatore di ripulire se stesso).

Puoi usare e riutilizzare la memoria come più ti piace, ma assicurati di aver deallocato tutte le risorse prima di uscire.




Sei corretto, la memoria viene automaticamente liberata quando il processo termina. Alcune persone si sforzano di non eseguire una pulizia approfondita quando il processo viene interrotto, poiché tutto verrà ceduto al sistema operativo. Tuttavia, mentre il programma è in esecuzione, è necessario liberare memoria non utilizzata. Se non lo fai, alla fine potresti esaurire o causare un numero eccessivo di pagine se il tuo set di lavoro diventa troppo grande.




Hai assolutamente ragione al riguardo. Nei piccoli programmi banali in cui una variabile deve esistere fino alla morte del programma, non vi è alcun reale vantaggio nel deallocare la memoria.

In effetti, una volta ero stato coinvolto in un progetto in cui ogni esecuzione del programma era molto complessa ma relativamente di breve durata, e la decisione era di mantenere la memoria assegnata e non destabilizzare il progetto facendo errori nella sua dislocazione.

Detto questo, nella maggior parte dei programmi questa non è davvero un'opzione, o può portare a esaurire la memoria.




Se un programma si dimentica di liberare alcuni Megabyte prima che esca, il sistema operativo li libererà. Ma se il tuo programma viene eseguito per settimane alla volta e un ciclo all'interno del programma dimentica di liberare alcuni byte in ogni iterazione, avrai una perdita di memoria che mangerà tutta la memoria disponibile nel tuo computer, a meno che non lo riavvii regolarmente basis => anche le piccole perdite di memoria potrebbero essere brutte se il programma viene utilizzato per un'attività seriamente importante anche se inizialmente non è stato progettato per uno.






Related


Tags

c   malloc   free