In Perl la gestione della memoria è automatizzata a livello di interprete. Storicamente, Perl è stato creato fin dall'inizio come un linguaggio in cui il programmatore non deve gestire esplicitamente la memoria, per concentrarsi sugli algoritmi. Il rilascio delle risorse avviene automaticamente, ma ogni sviluppatore deve conoscere i dettagli più importanti del funzionamento del meccanismo e le sue limitazioni.
Storia della questione:
Dalle prime versioni, i progettisti del linguaggio Perl hanno scelto un approccio in cui la memoria viene allocata dinamicamente e restituita al sistema in assenza di riferimenti all'oggetto. Questo è chiamato conteggio dei riferimenti (reference counting).
Problema:
La principale complessità è che il meccanismo non vede i riferimenti circolari. Se due strutture si riferiscono l'una all'altra, nessuna raggiunge "zero" nel contatore dei riferimenti e la memoria non viene liberata.
Soluzione:
Perl utilizza un contatore di riferimenti incorporato per ogni oggetto e variabile. Quando il contatore scende a zero, la memoria viene liberata automaticamente. Per combattere i riferimenti circolari, è consigliato utilizzare il modulo Scalar::Util::weaken per creare riferimenti "deboli" che non aumentano i contatori o rompere manualmente i cicli.
Esempio di codice:
use Scalar::Util 'weaken'; my $a = {}; my $b = { parent => $a }; $a->{child} = $b; weaken($a->{child});
Caratteristiche chiave:
Scalar::Util::weaken, Devel::Cycle) per il controllo della riferibilità.Può Perl rimuovere automaticamente i riferimenti circolari tramite garbage collection, come fa Java?
No. Nella versione standard di Perl 5 non esiste un vero garbage collector, solo il conteggio dei riferimenti. I riferimenti circolari vengono liberati solo manualmente.
Cosa succede alla memoria di una variabile se si fa undef su uno scalare o una struttura anonima?
L'operatore undef abbassa il contatore dei riferimenti. Se non ci sono altri riferimenti, la memoria sarà liberata. Ma se ci sono ancora riferimenti (ad esempio, da altre strutture), l'oggetto rimarrà in memoria.
my $a = []; my $b = $a; undef $a; # $b si riferisce ancora - la memoria non viene liberata
Se una variabile esce dall'ambito, la memoria viene sempre liberata?
No, se l'oggetto partecipa a un riferimento circolare o esiste un riferimento globale, la memoria non viene liberata fino a quando non vengono rimosse tutte le connessioni esterne.
Memorizziamo un albero di directory, dove ogni nodo conserva un riferimento al genitore e ai figli. Non usiamo riferimenti deboli. La memoria non viene liberata fino alla fine del programma.
Vantaggi:
Svantaggi:
Usiamo Scalar::Util::weaken per il riferimento genitore, in modo che il riferimento non aumenti il contatore, la memoria viene allocata esattamente quanto necessario.
Vantaggi:
Svantaggi: