Perl, otomatik bellek yönetimi için referans sayımı algoritmasını kullanır: her değişkenin bir referans sayacı vardır. Sayacı sıfıra ulaştığında, bellek serbest bırakılır. Çoğu durumda, bu saydam çalışır — kullanılmayan değişkenler, kapsamdan çıktıklarında silinir.
Problemler döngüsel referanslarla ortaya çıkar (örneğin, bir nesne kendisine veya iki yapı birbirine referans veriyorsa). Bu durumda, referans sayacı sıfıra asla ulaşamaz ve bellek serbest bırakılmaz.
Bellek sızıntılarını önlemek için Scalar::Util::weaken modülü kullanılır — bu, referans sayacını artırmayan "zayıf" referanslar oluşturmayı sağlar.
Örnek:
use Scalar::Util qw(weaken); my $a = {}; my $b = { ref => $a }; $a->{ref} = $b; weaken($a->{ref}); # artık döngüsel güçlü bir bağımlılık yok
Perl'in karmaşık karşılıklı yapıların bile, her zaman otomatik olarak tüm kullanılmayan belleği serbest bıraktığını varsaymak doğru mu?
Cevap ve örnek:
Hayır! Döngüsel referanslar söz konusu olduğunda, Perl otomatik olarak bellek serbest bırakamaz, weaken kullanılmadığı sürece:
my $a = {}; $a->{self} = $a; # döngü # $a otomatik olarak asla silinmeyecek — manuel bir kesme veya referansı zayıflatma gerekecek
Hikaye 1: Büyük bir Perl web hizmetinde bir bellek sızıntısı vardı — kullanıcı oturumları birbirlerine bir hash içinde referanslar tutuyordu ve kimse zayıf referansları kullanmıyordu. Hizmet, bir gün içinde tüm kaynakları tüketti, dondu ve yeniden başlatma gerektirdi.
Hikaye 2: Kendine ait ORM, User ve Group nesneleri arasında döngüler oluşturuyordu, her biri diğerine referans veriyordu. Kapsamdan çıktıktan sonra nesneler bellekte kaldı — hizmet yavaş yavaş onlara gigabaytlara kadar "şişti"!
Hikaye 3:
$self'e referans veren anonim altprogramların ("kapanışlar") sınıf yöntemleri olarak kullanılması, her nesne oluşturulduğunda sızıntılara yol açtı, ta ki döngüsel referansları tespit eden veweakengerektiğini belirten bir analiz aracı ortaya çıkana kadar.