j'ai cet exemple avec des fermetures imbriquées, ce qui démontre une fuite mémoirefermetures emboîtés et les variables capturées
use v5.10;
use strict;
package Awesome;
sub new {
bless {steps => [], surprise => undef}, shift;
}
sub say {
print "awesome: ", $_[1], "\n";
}
sub prepare {
my ($self, @steps) = @_;
for my $s (@steps) {
push @{$self->{steps}}, sub {
$self->say($s);
if ($s eq 'pony') {
$self->{surprise} = sub {
$s;
}
}
};
}
}
sub make {
my $self = shift;
while (my $step = shift @{$self->{steps}}) {
$step->();
}
if ($self->{surprise}) {
printf("And you have surprise: %s\n", $self->{surprise}->());
}
}
sub DESTROY {
warn "destroying";
}
package main;
my $a = Awesome->new;
$a->prepare('barbie','pony','flash');
$a->make();
sortie sur mon perl est
awesome: barbie
awesome: pony
awesome: flash
And you have surprise: pony
destroying at /tmp/t.pl line 43 during global destruction.
Et ce « lors de la destruction globale » signifie que l'objet couldn » t être détruit normalement, car il a quelques références circulaires.
Cependant, les seules références circulaires sont créés par
push @{$self->{steps}}, sub {
$self->say($s);
où nous utilisons auto à l'intérieur de la première fermeture $. Et plus tard dans make(), nous supprimerons ces étapes et les références circulaires. Mais ressemble à cette fermeture imbriquée avec "surprise" qui pose problème. Par exemple, si nous ne passons « poney » pour préparer() la production sera bonne comme prévu:
awesome: barbie
awesome: flash
destroying at /tmp/t.pl line 43.
fermetures Alors, est niché dans perl capture les mêmes variables que la fermeture de niveau supérieur déjà capturé même si nous ne les utilisez pas?
Oh, ils ont brisé la compatibilité en arrière :) Bon à savoir! –
@Oleg G, Pourquoi dites-vous réparer ce bug est une mauvaise chose? – ikegami
non, je ne pense pas que ce soit mauvais. Au contraire, je pense que c'est le cas où la rétrocompatibilité devrait être rompue. Désolé pour tromper –