Perl utilizza un algoritmo di conteggio dei riferimenti per la gestione automatica della memoria: ogni variabile ha un contatore di riferimenti. Quando il contatore diventa zero, la memoria viene liberata. Nella maggior parte dei casi, questo funziona in modo trasparente: le variabili non utilizzate vengono rimosse non appena escono dal proprio ambito.
Il problema si verifica con i riferimenti circolari (ad esempio, un oggetto si riferisce a se stesso o due strutture si riferiscono l'una all'altra). In questo caso, il contatore dei riferimenti non diventerà mai zero e la memoria non verrà liberata.
Per prevenire le perdite, viene utilizzato il modulo Scalar::Util::weaken — consente di creare riferimenti "debilitati" che non aumentano il contatore dei riferimenti.
Esempio:
use Scalar::Util qw(weaken); my $a = {}; my $b = { ref => $a }; $a->{ref} = $b; weaken($a->{ref}); # ora non c'è dipendenza ciclica forte
È corretto supporre che Perl liberi sempre automaticamente tutta la memoria non utilizzata, anche in presenza di strutture complesse interconnesse?
Risposta ed esempio:
No! In caso di riferimenti circolari, Perl non sarà in grado di liberare automaticamente la memoria a meno che non venga utilizzato weaken:
my $a = {}; $a->{self} = $a; # ciclo # $a non verrà mai eliminato automaticamente — sarà necessario un taglio manuale o un indebolimento del riferimento
Storia 1: In un grande servizio web Perl si è verificata una memory leak — le sessioni degli utenti mantenevano riferimenti l'uno all'altro in un hash, e nessuno utilizzava riferimenti indeboliti. Il servizio ha esaurito tutte le risorse in un giorno, si è bloccato e ha richiesto riavvii.
Storia 2: Un ORM fatto in casa creava cicli tra gli oggetti User e Group, ognuno dei quali si riferiva all'altro. Dopo l'uscita dall'ambito, gli oggetti rimanevano in memoria — il servizio è gradualmente "cresciuto" fino a decine di gigabyte!
Storia 3: L'uso di sottoprogrammi anonimi ("closure") come metodi di classe, che si riferivano a
$self, portava a perdite ad ogni creazione di oggetto, fino a quando non è stato creato un analizzatore che ha identificato i riferimenti circolari e ha indicato la necessità diweaken.