Naghaveer R
Naghaveer R

Reputation: 2944

How to suppress hash after insertion warning?

Use of each() on hash after insertion without resetting hash iterator results in undefined behavior, Perl interpreter: 0x13932010 at /srv/data203806/MUXmh-Migration/Newperl/localperl/lib/site_perl/5.18.1/x86_64-linux-thread-multi/forks.pm line 1736.

Everything in my code is working fine but I'm getting this error. How can I suppress this warning?

Upvotes: 5

Views: 2780

Answers (3)

ancient.wizard
ancient.wizard

Reputation: 21

The real question here is: what does happen? The documentation says it is undefined. As a Perl coder I can live with that. I personally don't care what set each() will return short of getting stuck in one place. There are a few possibilities but before I elaborate I should say that I use each() is a poor mans iterator since a built-in better than each() is not provided.

So the line up is: - Some random pair is returned from the key/value set and then moves on as expected form there. (this is okay with me, I'm not adding gobs of stuff) - Resets to start. clearly this is not happening or the documentation would say so. (I'm not in favor of this action) - each() returns the (undef,undef) set and then works as expected after that. Not my first choice but okay now and then if it happens to be one of the undefined possibilities. - looses its mind; I'd use a colorful metaphor here but basically loose all control and Perl breaks it-self. As best I can tell this does not happen.

As the other contributors suggested it's best to code so the warning is not created; however I provided one example (simple iterator) where I hit the each at a high frequency (higher) and I insert and remove items at a lower frequency. I find that Perl's behavior minus the warning message perfectly suitable.

In a few cases where I needed better iterator control I created a proper class to implement the behavior as I saw fit.

Upvotes: 2

Art Sackett
Art Sackett

Reputation: 11

The following technique, which minimally changes existing code, suppresses the warning by avoiding the dangerous operation:

foreach my $key (keys %hash) {
    my $value = $hash{$key};
    # ...
}

The assignment of $value ensures that you needn't rework the code that follows in the containing block.

Upvotes: 0

tobyink
tobyink

Reputation: 13664

This warns:

use strict;
use warnings;
use Data::Dumper;

my %h = (a=>1);
while (my ($k,$v) = each %h) {
   $h{b} = 2;
}

print Dumper \%h;

This silences the warning:

use strict;
use warnings;
use Data::Dumper;

my %h = (a=>1);
{
   no warnings qw(internal);
   while (my ($k,$v) = each %h) {
      $h{b} = 2;
   }
}

print Dumper \%h;

Note the warnings category to silence is called internal. How did I know this? Do I have some kind of amazing memory for Perl's warnings categories? No. All Perl's error and warnings messages are well documented in perldiag; for each warning, it mentions the category it belongs to.

That said, this warning is telling you about a real problem. The behaviour of your code is undefined; if you switch to a different version of Perl, it may suddenly start acting differently. Better than switching off the warning would be to fix your code!

In my example above, a quick fix would be to use each to loop through a copy of %h rather than %h itself.

use strict;
use warnings;
use Data::Dumper;

my %h = (a=>1);
{
   my %tmp = %h;
   while (my ($k,$v) = each %tmp) {
      $h{b} = 2;
   }
}

print Dumper \%h;

Upvotes: 12

Related Questions