Bug#417999: perl: GDBM tied hash weirdness - deletion in 'each' loop does nothing

Dominic Hargreaves dom at earth.li
Mon Apr 1 21:27:24 UTC 2013


tags 417999 +confirmed
retitle 417999 GDBM tied hash weirdness; deletion ends 'each' loop
thanks

On Thu, Apr 05, 2007 at 09:53:38PM -0400, Ian Zimmerman wrote:
> Try the following pearl:
> 
> ## begin test script
> 
> #! /usr/bin/perl
> 
> use GDBM_File;
> 
> %iddb = ();
> tie %iddb, 'GDBM_File', './weird', &GDBM_WRCREAT|&GDBM_NOLOCK, 0600;
> for (1..200) { $iddb{"foo$_"} = $_; }
> 
> print "Before deletion:\n\n";
> while (my ($k, $v) = each %iddb) { print "$k:$v\n"; }
> 
> while (my ($k, $v) = each %iddb) { delete $iddb{$k} if $v > 150 ; }
> print "\n\nAfter deletion:\n\n";
> while (my ($k, $v) = each %iddb) { print "$k:$v\n"; }
> 
> untie %iddb;
> 
> ## end test script

Not quite nothing; the first deletion in the second loop does happen, but
the loop is then broken out of. In other words, 'each' is returning undef
immediately after the successful deletion. This isn't what either the
perldoc for 'each' or 'delete' suggests should happen, and the 'GDBM_File'
manpage doesn't have anything useful either. It does look like a bug
(since perldoc -feach explicitly says you can delete the current hash
member from within an interation).

You can see this a bit more clearly with the following:

#! /usr/bin/perl

use GDBM_File;
use warnings;

%iddb = ();
tie %iddb, 'GDBM_File', './weird', &GDBM_WRCREAT|&GDBM_NOLOCK, 0600;

for (1..20) { $iddb{"$_"} = $_; }

print "Before deletion:\n\n";
while (my ($k, $v) = each %iddb) { print "$k:$v\n"; }

while (1) {
    sleep 1;
    $k = each %iddb;
    print "k is $k\n";
    delete $iddb{$k} if $k > 15;
}

The same behaviour was described way back in 1997, but at the time
the documentation didn't allow for deletion of the current iterator,
even though it worked in the simple case (no tie):

http://diswww.mit.edu/bloom-picayune.mit.edu/perl/7564

(search for GDBM)

It looks like a genuine bug, one way or another, and I'm probably going
to forward it upstream, better late than never.

-- 
Dominic Hargreaves | http://www.larted.org.uk/~dom/
PGP key 5178E2A5 from the.earth.li (keyserver,web,email)




More information about the Perl-maintainers mailing list