develooper Front page | perl.perl5.porters | Postings from April 2013

[perl #117449] GDBM tied hash weirdness; deletion ends 'each' loop

From:
Dominic Hargreaves
Date:
April 2, 2013 15:49
Subject:
[perl #117449] GDBM tied hash weirdness; deletion ends 'each' loop
Message ID:
rt-3.6.HEAD-28177-1364917752-38.117449-75-0@perl.org
# New Ticket Created by  Dominic Hargreaves 
# Please include the string:  [perl #117449]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=117449 >



This is a bug report for perl from dom@earth.li,
generated with the help of perlbug 1.39 running under perl 5.17.10.


-----------------------------------------------------------------
[Please describe your issue here]

The following bug was reported in Debian:
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=417999>

The test program which follows demonstrates that, contrary to all
available documentation (perlfunc and the minimal GDBM_File doc)
the current entry cannot be deleted from a GDBM tied hash:

#! /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;
}

Immediately after the delete, each apparently returns undef.

This behaviour appears to have been the case since roughly forever[1]
but it does go against documentated behaviour, so does appear to be
a genuine bug as far as I can see.

>From perlfunc:

               After "each" has returned all entries from the hash or array,
               the next call to "each" returns the empty list in list context
               and "undef" in scalar context; the next call following that one
               restarts iteration.  Each hash or array has its own internal
               iterator, accessed by "each", "keys", and "values".  The
               iterator is implicitly reset when "each" has reached the end as
               just described; it can be explicitly reset by calling "keys" or
               "values" on the hash or array.  If you add or delete a hash's
               elements while iterating over it, entries may be skipped or
               duplicated--so don't do that.  Exception: In the current
               implementation, it is always safe to delete the item most
               recently returned by "each()", so the following code works
               properly:

                       while (($key, $value) = each %hash) {
                         print $key, "\n";
                         delete $hash{$key};   # This is safe
                       }

[1] <http://diswww.mit.edu/bloom-picayune.mit.edu/perl/7564>


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=library
    severity=low
    module=GDBM_File
---
Site configuration information for perl 5.17.10:

Configured by dom at Sun Mar 31 23:53:26 BST 2013.

Summary of my perl5 (revision 5 version 17 subversion 10) configuration:
   
  Platform:
    osname=linux, osvers=3.2.0-4-686-pae, archname=i686-linux
    uname='linux callisto 3.2.0-4-686-pae #1 smp debian 3.2.39-2 i686 gnulinux '
    config_args='-de -Dprefix=/home/dom/perl5/perlbrew/perls/perl-5.17.10 -Dusedevel'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.7.2', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/i386-linux-gnu /lib/../lib /usr/lib/i386-linux-gnu /usr/lib/../lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.13'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'

Locally applied patches:
    

---
@INC for perl 5.17.10:
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/site_perl/5.17.10/i686-linux
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/site_perl/5.17.10
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/5.17.10/i686-linux
    /home/dom/perl5/perlbrew/perls/perl-5.17.10/lib/5.17.10
    .

---
Environment for perl 5.17.10:
    HOME=/home/dom
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/dom/perl5/perlbrew/bin:/home/dom/perl5/perlbrew/perls/perl-5.17.10/bin:~/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERLBREW_MANPATH=/home/dom/perl5/perlbrew/perls/perl-5.17.10/man
    PERLBREW_PATH=/home/dom/perl5/perlbrew/bin:/home/dom/perl5/perlbrew/perls/perl-5.17.10/bin
    PERLBREW_PERL=perl-5.17.10
    PERLBREW_ROOT=/home/dom/perl5/perlbrew
    PERLBREW_SKIP_INIT=1
    PERLBREW_VERSION=0.43
    PERL_BADLANG (unset)
    SHELL=/bin/bash




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About