deleting keys in restricted hashes was leaking the entry. Yow!
Nicholas Clark [Sat, 7 Feb 2004 21:46:59 +0000 (21:46 +0000)]
p4raw-id: //depot/perl@22281

hv.c
lib/Hash/Util.t

diff --git a/hv.c b/hv.c
index 097b599..669e55a 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -1005,6 +1005,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
         * an error.
         */
        if (SvREADONLY(hv)) {
+           SvREFCNT_dec(HeVAL(entry));
            HeVAL(entry) = &PL_sv_placeholder;
            /* We'll be saving this slot, so the number of allocated keys
             * doesn't go down, but the number placeholders goes up */
index 1c77728..8ed557f 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
         chdir 't';
     }
 }
-use Test::More tests => 159;
+use Test::More tests => 173;
 use strict;
 
 my @Exported_Funcs;
@@ -290,3 +290,36 @@ like( $@, qr/^Attempt to access disallowed key 'I_DONT_EXIST' in a restricted ha
 
 my $hash_seed = hash_seed();
 ok($hash_seed >= 0, "hash_seed $hash_seed");
+
+{
+    package Minder;
+    my $counter;
+    sub DESTROY {
+       --$counter;
+    }
+    sub new {
+       ++$counter;
+       bless [], __PACKAGE__;
+    }
+    package main;
+
+    for my $state ('', 'locked') {
+       my $a = Minder->new();
+       is ($counter, 1, "There is 1 object $state");
+       my %hash;
+       $hash{a} = $a;
+       is ($counter, 1, "There is still 1 object $state");
+
+       lock_keys(%hash) if $state;
+
+       is ($counter, 1, "There is still 1 object $state");
+       undef $a;
+       is ($counter, 1, "Still 1 object $state");
+       delete $hash{a};
+       is ($counter, 0, "0 objects when hash key is deleted $state");
+       $hash{a} = undef;
+       is ($counter, 0, "Still 0 objects $state");
+       %hash = ();
+       is ($counter, 0, "0 objects after clear $state");
+    }
+}