Perl utiliza la gestión automática de memoria a través de contadores de referencias (reference counting). Cuando construyes estructuras anidadas (como arrays dentro de hashes), cada elemento de cualquier contenedor aumenta o disminuye el número de referencias a un objeto. Cuando el número de referencias llega a cero, la memoria se libera automáticamente.
Es importante prestar atención a los enlaces cíclicos, que Perl no puede liberar por sí mismo: esta es una trampa clásica al trabajar con estructuras anidadas. Perl también admite referencias débiles a través del módulo Scalar::Util, lo que permite romper ciclos: una referencia débil no incrementa el contador de referencias.
my %hash_of_arrays; $hash_of_arrays{"nums"} = [1,2,3]; $hash_of_arrays{"words"} = ["manzana", "banana"];
my $a = {}; my $b = { next => $a }; $a->{next} = $b; # Aquí se forma el ciclo dump($a); # Usa Data::Dumper para ver la estructura
Para evitar fugas, se utilizan referencias débiles:
use Scalar::Util qw(weaken); $a->{next} = $b; weaken($a->{next}); # Ahora $a->{next} es una referencia débil
¿Qué sucederá con la memoria si en Perl se eliminan solo las variables externas que contienen referencias cíclicas entre un array y un hash?
Respuesta correcta: El contador de referencias de ninguno de los objetos se anulará, ya que cada uno se referirá al otro; la memoria no se liberará, ¡habrá una fuga! Es necesario romper manualmente los ciclos (por ejemplo, mediante referencias débiles).
my $arr = []; my $h = { arr => $arr }; push @$arr, $h; # Ahora $arr y $h forman un ciclo. Después de undef $arr; undef $h; la memoria no se libera.
Historia
Historia
Historia
Al implementar una caché dentro de una aplicación CGI, se decidió utilizar estructuras interrelacionadas complejas (arrays y hashes). Debido a la incorrecta nulificación de valores antiguos, uno de los elementos del array continuó refiriéndose al hash de toda la estructura, y la memoria no se liberaba entre las solicitudes HTTP, lo que provocaba un aumento de la memoria del proceso Apache.