Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDBM tied hash weirdness; deletion ends 'each' loop #12894

p5pRT opened this issue Apr 2, 2013 · 4 comments

GDBM tied hash weirdness; deletion ends 'each' loop #12894

p5pRT opened this issue Apr 2, 2013 · 4 comments


Copy link

p5pRT commented Apr 2, 2013

Migrated from (status was 'resolved')

Searchable as RT117449$

Copy link

p5pRT commented Apr 2, 2013

From @jmdh

Created by @jmdh

The following bug was reported in Debian​:

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

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

[1] <http​://>

Perl Info


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:
    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
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    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
  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:

Environment for perl 5.17.10:
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)

Copy link

p5pRT commented Dec 15, 2017


This weirdness arises because deleting from a gdbm hash can reorganise
the hash. Unlike Perl's own hashes, gdbm has no exception for deleting
the current entry. This is explained at some length in the gdbm
documentation. It is therefore impossible to make such deletion work as
desired, without making GDBM_File a far thicker layer over libgdbm than
it is clearly intended to be. I have put a note about this issue in the
GDBM_File documention in commit 3752113.


Copy link

p5pRT commented Dec 15, 2017

The RT System itself - Status changed from 'new' to 'open'

Copy link

p5pRT commented Dec 15, 2017

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

No branches or pull requests

1 participant