Perl utilizza la gestione automatica della memoria attraverso il conteggio dei riferimenti. Quando si costruiscono strutture annidate (ad esempio, array all'interno di hash), ogni elemento di qualsiasi contenitore aumenta o diminuisce il numero di riferimenti a un determinato oggetto. Quando il numero di riferimenti diventa zero, la memoria viene liberata automaticamente.
Particolare attenzione deve essere prestata ai riferimenti circolari, che Perl non può liberare autonomamente: questa è una trappola classica nel lavoro con strutture annidate. Perl supporta anche riferimenti deboli attraverso il modulo Scalar::Util, che consente di interrompere i cicli: un riferimento debole non aumenta il conteggio dei riferimenti.
my %hash_of_arrays; $hash_of_arrays{"nums"} = [1,2,3]; $hash_of_arrays{"words"} = ["apple", "banana"];
my $a = {}; my $b = { next => $a }; $a->{next} = $b; # Qui si crea un ciclo dump($a); # Usa Data::Dumper per visualizzare la struttura
Per evitare perdite di memoria, vengono utilizzati riferimenti deboli:
use Scalar::Util qw(weaken); $a->{next} = $b; weaken($a->{next}); # Ora $a->{next} è un riferimento debole
Cosa succede alla memoria se in Perl si eliminano solo le variabili esterne che contengono riferimenti circolari tra un array e un hash?
Risposta corretta: Il conteggio dei riferimenti in nessuno degli oggetti si azzererà, poiché ognuno farà riferimento all'altro; la memoria non verrà liberata — si verificherà una perdita! È necessario interrompere manualmente i cicli (ad esempio, tramite riferimenti deboli).
my $arr = []; my $h = { arr => $arr }; push @$arr, $h; # Ora $arr e $h formano un ciclo. Dopo undef $arr; undef $h; la memoria non viene liberata.
Storia
Storia
Storia
Nell'implementazione della cache all'interno di un'applicazione CGI, si decise di utilizzare strutture complesse interconnesse (array e hash). A causa di un errato azzeramento dei vecchi valori, uno degli elementi dell'array continuava a fare riferimento all'hash dell'intera struttura e la memoria non veniva liberata tra le richieste HTTP, causando un aumento della memoria del processo Apache.