Tarihsel olarak Perl, değişkenlerin leksikal kapsamını destekler, bu da dış çevreyi saklayan fonksiyonlar olan kapalı alanların (closures) kullanılmasına olanak tanır. Sorun, kapalı alanın kendi kapsamının dışındaki değişkenlere atıfta bulunması veya iç içe yapılarının döngüsel referanslar oluşturması durumunda ortaya çıkar; bu, referanslara dikkat edilmediğinde bellek sızıntısına yol açar.
Çözüm: Kapalı alanları, fonksiyon fabrikaları ve fonksiyonel stil oluşturmak için kullanın ve dış kapsamdan değişkenleri kapattığınızda referansların doğru yönetimini hatırlayın.
Kod örneği:
sub make_counter { my $count = 0; return sub { $count++; }; } my $counter = make_counter(); print $counter->(), " "; # 0 print $counter->(), " "; # 1
Anahtar özellikler:
Kendisine referans veren anonim bir fonksiyon döndürdüğünde ne olur?
Döngüsel bir referans oluşturulacaktır ve Perl bunu otomatik olarak çöp toplayıcı ile temizleyemez. Bu, bellek sızıntısına yol açar. Çözüm olarak zayıf referansları kullanın, Scalar::Util modülü:
use Scalar::Util qw(weaken); my $foo; $foo = sub { ... $foo ... }; weaken($foo);
Kapalı alan her zaman değişkenin «kopyasını» mı alır, yoksa aynı değişkene mi referans verir?
Kapalı alan her zaman mevcut değişken ile çalışır, onun kapsamı closure oluşturulurken sabitlenir. Bu nedenle, değişken her çağrıda aynı kalır.
Kapalı alanın dışarıda değiştirilebilir bir durumla çalışmasını sağlamak ama buna güçlü bir referans tutmamasını sağlamak mümkün mü?
Evet, zayıf referanslar (Scalar::Util::weaken) kullanın veya kodu yapısallaştırın, böylece referanslar yalnızca gerekli yerlerde tutulur (örneğin, her closure çağrısında verileri dışarıdan geçirin).
Bir callback-closure oluşturuldu, OO-objesinden $self'i kapatıyor ve callbacks hash'inin içinde tutuluyor. Nesne yok edildikten sonra bellek boşaltılmıyor.
Artıları:
Eksileri:
Closure, Scalar::Util::weaken ile $self'ye zayıf bir şekilde referans verir:
use Scalar::Util qw(weaken); my $cb = sub { my $self = shift; weaken($self); ... };
Artıları:
Eksileri: