插入警告后如何抑制哈希?

时间:2014-03-28 10:31:09

标签: perl

  

在插入后使用each()而不重置哈希迭代器导致未定义的行为,Perl解释器:0x13932010/srv/data203806/MUXmh-Migration/Newperl/localperl/lib/site_perl/5.18.1/x86_64-linux-thread-multi/forks.pm第1736行。

我的代码中的所有内容都运行正常,但我收到此错误。我怎么能抑制这个警告?

3 个答案:

答案 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的赋值确保您不需要重写包含块中的后续代码。