Reputation: 2944
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
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
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
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