Skip to content

Commit f50383f

Browse files
Ton HospelFather Chrysostomos
Ton Hospel
authored and
Father Chrysostomos
committed
[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
1 parent 3489904 commit f50383f

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

hv.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,26 +1040,30 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
10401040
mro_changes = 1;
10411041
}
10421042

1043-
if (d_flags & G_DISCARD)
1044-
sv = NULL;
1045-
else {
1046-
sv = sv_2mortal(HeVAL(entry));
1047-
HeVAL(entry) = &PL_sv_placeholder;
1048-
}
1043+
if (d_flags & G_DISCARD) {
1044+
sv = HeVAL(entry);
1045+
if (sv) {
1046+
/* deletion of method from stash */
1047+
if (isGV(sv) && isGV_with_GP(sv) && GvCVu(sv)
1048+
&& HvENAME_get(hv))
1049+
mro_method_changed_in(hv);
1050+
SvREFCNT_dec(sv);
1051+
sv = NULL;
1052+
}
1053+
} else sv = sv_2mortal(HeVAL(entry));
1054+
HeVAL(entry) = &PL_sv_placeholder;
10491055

10501056
/*
10511057
* If a restricted hash, rather than really deleting the entry, put
10521058
* a placeholder there. This marks the key as being "approved", so
10531059
* we can still access via not-really-existing key without raising
10541060
* an error.
10551061
*/
1056-
if (SvREADONLY(hv)) {
1057-
SvREFCNT_dec(HeVAL(entry));
1058-
HeVAL(entry) = &PL_sv_placeholder;
1062+
if (SvREADONLY(hv))
10591063
/* We'll be saving this slot, so the number of allocated keys
10601064
* doesn't go down, but the number placeholders goes up */
10611065
HvPLACEHOLDERS(hv)++;
1062-
} else {
1066+
else {
10631067
*oentry = HeNEXT(entry);
10641068
if (SvOOK(hv) && entry == HvAUX(hv)->xhv_eiter /* HvEITER(hv) */)
10651069
HvLAZYDEL_on(hv);

0 commit comments

Comments
 (0)