In Perl is geheugenbeheer geautomatiseerd op het niveau van de interpreter. Historisch gezien is Perl vanaf het begin ontworpen als een taal waarin de programmeur niet expliciet geheugen hoeft te beheren, zodat hij zich kan concentreren op algoritmes. Het vrijgeven van bronnen gebeurt automatisch, maar de belangrijkste details van het mechanisme en de beperkingen daarvan moet elke ontwikkelaar kennen.
Geschiedenis van de kwestie:
Vanaf de eerste versies van Perl kozen de ontwikkelaars van de taal voor een benadering waarbij geheugen dynamisch wordt toegewezen en weer aan het systeem wordt teruggegeven bij gebrek aan verwijzingen naar een object. Dit wordt referentietelling (reference counting) genoemd.
Probleem:
De belangrijkste nuance is dat het mechanisme cyclische verwijzingen niet ziet. Als twee structuren naar elkaar verwijzen, zal geen van beiden "nul" bereiken in de referentieteller, en zal het geheugen niet worden vrijgegeven.
Oplossing:
Perl gebruikt een ingebouwde referentieteller voor elk object en elke variabele. Wanneer de teller op nul valt, wordt het geheugen automatisch vrijgegeven. Om cyclische verwijzingen te bestrijden, wordt aangeraden om de module Scalar::Util::weaken te gebruiken om "verzwakte" verwijzingen te maken die de tellers niet verhogen, of om de cycli handmatig te doorbreken.
Voorbeeldcode:
use Scalar::Util 'weaken'; my $a = {}; my $b = { parent => $a }; $a->{child} = $b; weaken($a->{child});
Belangrijke kenmerken:
Scalar::Util::weaken, Devel::Cycle) voor het controleren van verwijzing.Kan Perl cyclische verwijzingen automatisch verwijderen door garbage collection, zoals Java dat doet?
Nee. In de standaardimplementatie van Perl 5 is er geen volwaardige garbage collector, alleen referentietelling. Cyclische verwijzingen worden alleen handmatig vrijgegeven.
Wat gebeurt er met het geheugen van een variabele als je undef toepast op een scalair of anonieme structuur?
De operator undef verlaagt de referentieteller. Als er geen andere verwijzingen meer zijn, wordt het geheugen vrijgegeven. Maar als er nog verwijzingen zijn (bijvoorbeeld vanuit andere structuren), blijft het object in het geheugen.
my $a = []; my $b = $a; undef $a; # $b verwijst nog steeds — geheugen wordt niet vrijgegeven
Als een variabele uit de scope verdwijnt, wordt het geheugen dan altijd vrijgegeven?
Nee, als een object deel uitmaakt van een cyclische verwijzing of er is een globale verwijzing, wordt het geheugen pas vrijgegeven als alle externe verbindingen zijn opgelost.
We bewaren een boom van mappen waarin elke knoop een verwijzing naar de ouder en naar de nakomelingen opslaat. We gebruiken geen verzwakte verwijzingen. Geheugen wordt niet vrijgegeven tot het programma is beëindigd.
Voordelen:
Nadelen:
We gebruiken Scalar::Util::weaken voor de ouderverwijzing, zodat de verwijzing de teller niet verhoogt, en er wordt precies zoveel geheugen toegewezen als nodig is.
Voordelen:
Nadelen: