From: Nicholas Clark Date: Tue, 16 Apr 2002 22:22:41 +0000 (+0100) Subject: Re: Unbalanced string table refcount (was: perl@15930) X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fe7bca907fe77f091cc40c458c768c0db469e921;p=p5sagit%2Fp5-mst-13.2.git Re: Unbalanced string table refcount (was: perl@15930) Message-ID: <20020416212241.GA315@Bagpuss.unfortu.net> p4raw-id: //depot/perl@15958 --- diff --git a/embed.fnc b/embed.fnc index 20517df..45c9d96 100644 --- a/embed.fnc +++ b/embed.fnc @@ -278,7 +278,7 @@ Apd |char* |hv_iterkey |HE* entry|I32* retlen Apd |SV* |hv_iterkeysv |HE* entry Apd |HE* |hv_iternext |HV* tb Apd |SV* |hv_iternextsv |HV* hv|char** key|I32* retlen -ApM |HE* |hv_iternext_flags|HV* tb|I32 flags +ApMd |HE* |hv_iternext_flags|HV* tb|I32 flags Apd |SV* |hv_iterval |HV* tb|HE* entry Ap |void |hv_ksplit |HV* hv|IV newmax Apd |void |hv_magic |HV* hv|GV* gv|int how diff --git a/global.sym b/global.sym index cc4d2a1..dec0480 100644 --- a/global.sym +++ b/global.sym @@ -208,6 +208,7 @@ Perl_is_utf8_string Perl_is_utf8_alnum Perl_is_utf8_alnumc Perl_is_utf8_idfirst +Perl_is_utf8_idcont Perl_is_utf8_alpha Perl_is_utf8_ascii Perl_is_utf8_space diff --git a/hv.c b/hv.c index 51f47fd..02a0955 100644 --- a/hv.c +++ b/hv.c @@ -1758,6 +1758,14 @@ Perl_hv_iterinit(pTHX_ HV *hv) Returns entries from a hash iterator. See C. +You may call C or C on the hash entry that the +iterator currently points to, without losing your place or invalidating your +iterator. Note that in this case the current entry is deleted from the hash +with your iterator holding the last reference to it. Your iterator is flagged +to free the entry on the next call to C, so you must not discard +your iterator immediately else the entry will leak - call C to +trigger the resource deallocation. + =cut */ @@ -1768,11 +1776,19 @@ Perl_hv_iternext(pTHX_ HV *hv) } /* -XXX=for apidoc hv_iternext - -Returns entries from a hash iterator. See C. +=for apidoc hv_iternext_flags + +Returns entries from a hash iterator. See C and C. +The C value will normally be zero; if HV_ITERNEXT_WANTPLACEHOLDERS is +set the placeholders keys (for restricted hashes) will be returned in addition +to normal keys. By default placeholders are automatically skipped over. +Currently a placeholder is implemented with a value that is literally +<&Perl_sv_undef> (a regular C value is a normal read-write SV for which +C is false). Note that the implementation of placeholders and +restricted hashes may change, and the implementation currently is +insufficiently abstracted for any change to be tidy. -XXX=cut +=cut */ HE * diff --git a/universal.c b/universal.c index 550ea4d..926d1c3 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) {