在插入后使用
each()
而不重置哈希迭代器导致未定义的行为,Perl解释器:0x13932010
在/srv/data203806/MUXmh-Migration/Newperl/localperl/lib/site_perl/5.18.1/x86_64-linux-thread-multi/forks.pm
第1736行。
我的代码中的所有内容都运行正常,但我收到此错误。我怎么能抑制这个警告?
答案 0 :(得分:11)
警告:
use strict;
use warnings;
use Data::Dumper;
my %h = (a=>1);
while (my ($k,$v) = each %h) {
$h{b} = 2;
}
print Dumper \%h;
这使警告无声:
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;
请注意,静音的警告类别称为internal
。我怎么知道这个?对于Perl的警告类别,我有一些惊人的记忆吗?不是。所有Perl的错误和警告消息都在perldiag中有详细记录;对于每个警告,它都会提到它所属的类别。
那就是说,这个警告告诉你一个真正的问题。您的代码行为未定义;如果你切换到不同版本的Perl,它可能突然开始采取不同的行动。关闭警告比修复你的代码更好!
在上面的示例中,快速解决方法是使用each
循环遍历%h
的副本,而不是%h
本身。
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;
答案 1 :(得分:1)
这里真正的问题是:会发生什么?文档说这是未定义的。作为Perl编码器,我可以忍受它。我个人并不关心每个()会在一个地方停留的情况。有一些可能性,但在我详细说明之前我应该说我使用each()是一个糟糕的勒芒迭代器,因为没有提供比每个()更好的内置。
所以排队是: - 从键/值集返回一些随机对,然后按预期形式在那里继续。 (这对我来说没关系,我没有添加大量的东西) - 重置开始。显然这没有发生,或文件会这么说。 (我不赞成这个动作) - each()返回(undef,undef)集合,然后按预期工作。不是我的第一选择,但现在好吧,如果它恰好是未定义的可能性之一。 - 失去理智;我在这里使用了一个色彩缤纷的比喻,但基本上放松了所有的控制,Perl打破了它自我。最好我可以说这不会发生。
正如其他贡献者所建议的那样,它最好编码,因此不会创建警告;然而,我提供了一个例子(简单的迭代器),我以高频率(更高)击中每个,我插入和删除较低频率的项目。我发现Perl的行为减去警告信息非常合适。
在我需要更好的迭代器控制的一些情况下,我创建了一个适当的类来实现我认为合适的行为。
答案 2 :(得分:-1)
以下技术最低限度地更改现有代码,通过避免危险操作来抑制警告:
foreach my $key (keys %hash) {
my $value = $hash{$key};
# ...
}
$ value的赋值确保您不需要重写包含块中的后续代码。