summaryrefslogtreecommitdiff
path: root/universal.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2002-04-16 23:22:41 +0100
committerJarkko Hietaniemi <jhi@iki.fi>2002-04-16 22:05:07 +0000
commitfe7bca907fe77f091cc40c458c768c0db469e921 (patch)
tree2fea22add731aa2ab7449ce62dcf2bb69f3b6b15 /universal.c
parent16537909412fc4f9eac20f6fc9a1b80bddb3cdd5 (diff)
downloadperl-fe7bca907fe77f091cc40c458c768c0db469e921.tar.gz
Re: Unbalanced string table refcount (was: perl@15930)
Message-ID: <20020416212241.GA315@Bagpuss.unfortu.net> p4raw-id: //depot/perl@15958
Diffstat (limited to 'universal.c')
-rw-r--r--universal.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/universal.c b/universal.c
index 550ea4dfee..926d1c349d 100644
--- a/universal.c
+++ b/universal.c
@@ -520,9 +520,16 @@ XS(XS_Internals_hv_clear_placehold)
I32 riter = HvRITER(hv);
HE *eiter = HvEITER(hv);
hv_iterinit(hv);
- while (items
- && (entry
- = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))) {
+ /* This may look suboptimal with the items *after* the iternext, but
+ it's quite deliberate. We only get here with items==0 if we've
+ just deleted the last placeholder in the hash. If we've just done
+ that then it means that the hash is in lazy delete mode, and the
+ HE is now only referenced in our iterator. If we just quit the loop
+ and discarded our iterator then the HE leaks. So we do the && the
+ other way to ensure iternext is called just one more time, which
+ has the side effect of triggering the lazy delete. */
+ while ((entry = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))
+ && items) {
SV *val = hv_iterval(hv, entry);
if (val == &PL_sv_undef) {