Empecé notando algo extraño sobre Scope::Guard
.DESTROY llamado en la secuencia inesperada
- Si UNDEF una variable
$guard
como la última declaración en un sub, sub del guardia se llamada más tarde de lo esperado. - Si no lo defino, o si hago algo (cualquier cosa) después de
undef $guard
, se llama cuando la referencia sale del alcance según lo documentado. Me pregunto porque.
el código es que también se encuentran here
my $sClass = 'SGuard';
# Uncomment to use Scope::Guard instead:
# use Scope::Guard; $sClass = 'Scope::Guard';
package SGuard;
sub new {
my ($class, $sub) = @_;
return bless { sub => $sub }, $class;
}
sub DESTROY {
my ($self) = @_;
$self->{sub}->();
}
package main;
sub mySub {
my $mySubGuard = $sClass->new(sub {
print "shouldDestroyFirst\n"
});
# Do something - any no-op will do.
undef;
# Comment out this line and it works
undef $mySubGuard;
# Or uncomment the next undef line and it works. Any statement(s) or
# no-ops will do but we test the return value of mySub to make sure it
# doesn't return a reference, so undef...
# undef;
}
{
my $scopeGuard = $sClass->new(sub {
print "shouldDestroyLast\n"
});
# Check that mySub returns undef to ensure the reference *did* go out
# of scope
printf "mySub returned a %sdefined value\n", defined mySub() ? "" : "un";
}
print "done\n";
En el código que he hecho mi propio hombre pobre Scope::Guard
(SGuard
arriba) sólo para hacer el ejemplo más simple posible. También puede usar Scope::Guard
y obtener exactamente los mismos resultados que son inesperados al menos para mí.
Estoy esperando que el $mySubGuard
dentro mySub()
deben ser destruidos primera y la $scopeGuard
en el ámbito que llama mySub()
deben ser destruidos pasado. Y así obtener una salida como:
shouldDestroyFirst
mySub returned a undefined value
shouldDestroyLast
done
me sale por encima de la salida si uso undef $mySubGuard
línea en mySub. Si yo no uso undef $mySubGuard
línea en mySub, consigo debajo de la salida:
mySub returned a undefined value
shouldDestroyLast
shouldDestroyFirst
done
Por lo tanto, parece que el $mySubGuard
de mySub()
se destruye después de las variables locales con el ámbito exterior son destruidos.
¿Por qué el comportamiento difiere solo porque undef una variable que está a punto de ir fuera de alcance de todos modos? ¿Y por qué importa si se hace algo después de ?