【问题标题】:What are Data::Dumper()'s side effects?Data::Dumper() 的副作用是什么?
【发布时间】:2011-07-21 15:54:55
【问题描述】:

如果我将Dumper($cmd_string) 注释掉,那么while 循环将永远不会被执行。

Dumper() 对 $cmd_string 有什么副作用?

这是 $cmd_string 在 sub 调用之前的内容:

VAR1 = {
    'The Java Runtime Library' => {
        'apt-get install -y' => 'sun-java6-jre'
    }
};


sub installPackages
{
    my $cmd_string = shift;
    my %rc_hash;

    my $rc;

    Dumper($cmd_string);

    for my $desc (keys %{$cmd_string})
    {
        while (my ($cmd, $arg) = each %{$cmd_string->{$desc}})
        {
            print "system($cmd $arg)\n";

            $rc = system("$cmd $arg");

            if ($rc)
            {
                $rc_hash{$desc}{$cmd} = '';
            }
        }
    }
    return \%rc_hash;
}

如果我在没有 Dumper() 的情况下运行 Perl 调试器并在 $cmd_string 上使用 x 命令,那么它可以工作,但如果我只是单步执行代码,它就不起作用。

这是在仅单步执行子末尾的代码之后

  DB<3> x $cmd_string
0  HASH(0x2769550)
   '' => HASH(0x2769880)
        empty hash
   'The Java Runtime Library' => HASH(0x25cc2a0)
      'apt-get install -y' => 'sun-java6-jre'
  DB<4> x $cmd_string->{$desc}
0  HASH(0x2769880)
     empty hash

现在,如果我在 for 循环之前 x $cmd_string 我会在子结束时得到这个

main::installPackages(msi.pl:1979):       return \%rc_hash;
  DB<3> x $cmd_string
0  HASH(0x1125490)
   'The Java Runtime Library' => HASH(0xf852a0)
      'apt-get install -y' => 'sun-java6-jre'

【问题讨论】:

    标签: perl debugging side-effects


    【解决方案1】:

    each 哈希迭代器使用隐藏的每个哈希变量来跟踪它在哈希中的位置。我的猜测是用于生成$cmd_string 哈希的代码也使用了each,但没有迭代完成。

    要重置 each 迭代器,请将 keys %{$cmd_string-&gt;{$desc}}; 放在 while 循环之前。在 void 上下文中调用 keys 是重置哈希迭代器的标准方法。

    或者,只需使用for my $cmd (keys %{$cmd_string-&gt;{$desc}}) {,然后在循环内创建$arg 变量。

    使用Dumper() 解决问题的原因是Dumper 最有可能在哈希上调用keys,从而重置迭代器。

    【讨论】:

    • 至少一个非常旧版本的 Dumper 在它转储的哈希值的末尾意外地离开了迭代器。
    • Dumper() 确实重置了内部迭代器。这会导致无限循环:perl -MData::Dumper -e '%x = (0,0); Dumper %x while $k = each %x'
    • each 永远不应该用于包装函数调用。对于您描述的迭代器问题,最好完全避免它。
    猜你喜欢
    • 1970-01-01
    • 2010-11-07
    • 2017-04-15
    • 2012-06-06
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    相关资源
    最近更新 更多