DB_File WTF (was GDBM_File WTF?)
Dirk Koopman
djk at tobit.co.uk
Sun Apr 8 19:24:29 BST 2007
Andy Armstrong wrote:
> On 8 Apr 2007, at 18:25, Dirk Koopman wrote:
>
>> I see to be getting a similar and rather more final problem along a
>> similar vein. Except that it bangs out with:
>>
>> Out of memory during ridiculously large request at
>> /spider/perl/DXDupe.pm line 78.
>>
>> $dbm = tie (%d, 'DB_File', $fn);
>>
>> ..
>> ..
>>
>> if ($main::systime - $lasttime >= 3600) {
>> while (($k, $v) = each %d) {
>> delete $d{$k} if $main::systime >= $v; # line 78
>> }
>> $lasttime = $main::systime;
>> }
>>
>> But only on the latest freebsd 6.2.
>>
>> Any clues?
>
> Did you miss my post? It's not safe to modify the tied hash during
> iteration. That's a limitation the Perl wrapper inherits from the
> underlying library.
>
Mind you, I was lead astray by this (from perlfunc "each")
When the hash is entirely read, a null array is returned in
list context (which when assigned produces a false (0) value),
and "undef" in scalar context. The next call to "each" after
that will start iterating again. There is a single iterator
for each hash, shared by all "each", "keys", and "values" func‐
tion calls in the program; it can be reset by reading all the
elements from the hash, or by evaluating "keys HASH" or "values
HASH". If you add or delete elements of a hash while you’re
iterating over it, you may get entries skipped or duplicated,
so don’t. Exception: It is always safe to delete the item most
recently returned by "each()", which means that the following
code will work:
while (($key, $value) = each %hash) {
print $key, "\n";
delete $hash{$key}; # This is safe
}
Note the gratuitous use of the word "safe" in official perl
documentation :-)
More information about the london.pm
mailing list