Ci sono due posti in cui le variabili possono essere memorizzate. Quando crei una variabile come questa:
int a;
char c;
char d[16];
Le variabili vengono create nello " stack ". Le variabili di stack vengono automaticamente liberate quando escono dall'ambito (ovvero, quando il codice non può più raggiungerle). Potresti sentirle chiamate variabili "automatiche", ma questo è passato di moda.
Molti esempi per principianti useranno solo variabili di stack.
Lo stack è carino perché è automatico, ma ha anche due svantaggi: (1) Il compilatore deve sapere in anticipo quanto sono grandi le variabili e (b) lo spazio dello stack è alquanto limitato. Ad esempio: in Windows, nelle impostazioni predefinite del linker Microsoft, lo stack è impostato su 1 MB e non tutto è disponibile per le variabili.
Se non sai in fase di compilazione quanto è grande il tuo array, o se hai bisogno di un grande array o struct, hai bisogno del "piano B".
Il piano B è chiamato " mucchio ". Di solito puoi creare variabili grandi quanto il sistema operativo ti consente, ma devi farlo da solo. I post precedenti ti hanno mostrato un modo per farlo, sebbene ci siano altri modi:
int size;
// ...
// Set size to some value, based on information available at run-time. Then:
// ...
char *p = (char *)malloc(size);
(Si noti che le variabili nell'heap non vengono manipolate direttamente, ma tramite puntatori)
Dopo aver creato una variabile di heap, il problema è che il compilatore non può dire quando hai finito, quindi perdi il rilascio automatico. È qui che entra in gioco il "rilascio manuale" a cui ti riferivi. Il tuo codice ora è responsabile di decidere quando la variabile non è più necessaria e rilasciala in modo che la memoria possa essere utilizzata per altri scopi. Per il caso precedente, con:
free(p);
Ciò che rende questa seconda opzione un "brutto affare" è che non è sempre facile sapere quando la variabile non è più necessaria. Dimenticare di rilasciare una variabile quando non ne hai bisogno farà sì che il tuo programma consumi più memoria di cui ha bisogno. Questa situazione è chiamata "perdita". La memoria "trapelata" non può essere utilizzata per nulla finché il programma non termina e il sistema operativo non recupera tutte le sue risorse. Sono possibili problemi anche più fastidiosi se rilasci una variabile di heap per errore prima di averla effettivamente terminata.
In C e C ++, sei responsabile della pulizia delle variabili di heap come mostrato sopra. Tuttavia, ci sono linguaggi e ambienti come Java e .NET come C # che utilizzano un approccio diverso, in cui l'heap viene ripulito da solo. Questo secondo metodo, chiamato "garbage collection", è molto più semplice per lo sviluppatore ma si paga una penalità in termini di overhead e prestazioni. È un equilibrio.
(Ho sorvolato su molti dettagli per dare una risposta più semplice, ma spero più livellata)