[Warszawa-pm] Scope::Guard

Piotr Fusik piotr w fusik.info
Pią, 12 Paź 2012, 00:09:40 PDT


Perl nie jest tu wyjątkiem: tak samo jest w Java, C#, JavaScript.
Wszystkie te języki mają garbage collector, którego zadaniem jest zwalnianie 
pamięci w programie, ale nie kontrola zasobów takich jak otwarte pliki. 
Jeśli otwierasz plik, nie zamykasz go i czekasz, aż destruktor wołany z 
garbage collectora zamknie plik, to jesteś ciapa programista. Pewnie kiedyś 
zamknie, ale nie masz nad tym kontroli.

W C# jest coś w rodzaju Score::Guard:

using (Stream s = File.OpenRead("foo")) {
...
}

co jest cukrem składniowym dla:

Stream s = File.OpenRead("foo");
try {
  ...
}
finally {
   s.Dispose(); // jawne wywołanie metody, która ma zwolnić zewnętrzne 
zasoby
}

Analogiczną konstrukcję dodali w Javie 7.

Rozumiem, że Dexterowi chodzi o destruktory ala C++ dla obiektów na stosie. 
Ale w tym języku ciapa programista może zrobić sobie dużo innych 
boleśniejszych kuku.

Piotr

Dnia 2012-10-11 21:39 Piotr Roszatycki napisał(a):

>Tak, takich mechanizmów jest multum. Chodziło mi o to, że w Perlu nie
>ma czegoś takiego jak destruktor obiektów. Przykładowy kod:
>
>#!/usr/bin/perl
>package My::Class;
>use Moose;
>
>has 'ref' => (is => 'rw', clearer => 'clear_ref');
>
>sub free {
>    my ($self) = @_;
>    $self->clear_ref;
>}
>
>sub DESTROY {
>    warn "memory leak of @_" if ${^GLOBAL_PHASE} eq 'DESTRUCT';
>}
>
>package main;
>my $obj1 = My::Class->new();
>my $obj2 = My::Class->new();
>
># zapętlam
>$obj1->ref($obj2);
>$obj2->ref($obj1);
>
>#$obj1->free;
>#$obj2->free;
>
># zero efektu jeśli powyższe jest zakomentowane
>undef $obj1;
>undef $obj2;
>
>
>i teraz trick polega na tym, że ten DESTROY to nie jest destruktor! To
>jest jedynie procedura, która uruchamia się już po tym, jak obiekt
>ulega destrukcji. W tym powyższym przypadku wykona się dopiero na
>koniec programu (global destruction), stąd komunikat o "memory leak".
>
>Jeśli zrobię metodę, która ręcznie zwolni mi zapętlone referencje i
>wywołam ją explicite albo pośrednio z użyciem tego Scope::Guard, to
>faktycznie pamięć się zwolni. Jednak to trzeba ręcznie obsłużyć z
>zewnątrz klasy. Jak jakaś ciapa programista zapomni wywołać "free" to
>kaplica, bo sam undef obiektu to za mało. Fajnie byłoby, gdyby
>zwalniając $obj1 ten "free" wywołałby się automatycznie, albo
>odwrotnie: wywołując "free" zwolniłby się automatycznie $obj1.
>
>Pzdr.
>
>
>2012/10/11 Zbigniew Łukasiak <zzbbyy w gmail.com>
>>
>> http://search.cpan.org/~chocolate/Scope-Guard-0.20/lib/Scope/Guard.pm
>>
>> tak a propos rozmowy na ostatnim spotkaniu
>_______________________________________________
>Warszawa-pm mailing list
>Warszawa-pm w pm.org
>http://mail.pm.org/mailman/listinfo/warszawa-pm
>
>



Więcej informacji o liście Warszawa-pm