[perl #85026] Deleting the current iterator in void context
authorTon Hospel <me-02@ton.iguana.be>
Fri, 20 May 2011 00:05:16 +0000 (17:05 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 20 May 2011 01:01:46 +0000 (18:01 -0700)
commitf50383f58716bc0faa50de094d47cad8ad3fcbdb
tree30faefd41126b00631bc62d972b2a00f86e604f9
parent348990471457e062920a311769ddae09a49fa203
[perl #85026] Deleting the current iterator in void context

Looking at the delete code I see another strange thing. If the delete
of the current iterator is done with the G_DISCARD flag, the corres-
ponding value is not freed and survives until the lazy deleted entry
gets removed on the next hash iteration. This is easily demonstrated
like this:

perl -wle '
sub DESTROY { print "DESTROY" }
%a=(a=>bless[]);
each %a;
delete $a{a};
print "END"
'

This prints:

END
DESTROY

notice the difference with:

perl -wle '
sub DESTROY { print "DESTROY" }
%hash = (a => bless[]);
each %hash;
$dummy = delete $hash{a}; $dummy = 0;
print "END"
'

This prints:

DESTROY
END

This is easily solved by always replacing the deleted entry value with
&PL_sv_placeholder. It actually simplifies the code a bit except for the
fact that the mro_method_changed from free_hash_ent now has to be done
in hv_delete
hv.c