为什么undef变量变成没有定义的{}?

min*_*_he 3 perl

我正在研究Webmin的源代码

($wuser) = grep { $_->{'name'} eq $in{'user'} } &acl::list_users();

如果我们$in{'user'}像这样传递?user=notexist,变量$wuser将是undef,不是吗?

抽象代码描述了下面发生的情况。

# $wuser is undef now.
#die Dumper($wuser);
if($wuser){die 'not die here';}
        if ($wuser->{'pass'} eq 'x') {
                #never reach here.
                die 'not die in branch 1';
        }
        elsif ($wuser->{'pass'} eq '*LK*' ||
               $wuser->{'pass'} =~ /^\!/) {
                #never reach here too.
                die 'not die in branch 2';
        }
if($wuser){die 'so....why die here '.Dumper($wuser);}
# $wuser is {} now.
}

Run Code Online (Sandbox Code Playgroud)

所以...什么时候以及如何undef变量变成{}而没有任何定义...

Dav*_*oss 8

这里的问题是Perl功能,称为“自动生存”。基本上,这意味着,如果将未定义的Perl变量视为引用类型,则Perl将创建该类型的引用并将其存储在变量中。

因此,当您执行以下语句时,您的问题就开始了:

if ($wuser->{'pass'} eq 'x')
Run Code Online (Sandbox Code Playgroud)

Perl将您$wuser视为哈希引用,因此它将创建一个空哈希并将该哈希的引用存储在中$wuser。然后,它可以在该哈希中查找“ pass”键,并发现它不存在。

通常,这被视为功能。您可以运行如下代码:

my $hash; # created as undef
$hash->{foo}{bar}{baz} = 1;
Run Code Online (Sandbox Code Playgroud)

Perl将为您创建此数据结构:

{
  'foo' => {
    'bar' => {
      'baz' => 1
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

您无需费心创建哈希的所有中间级别。

当然,您的代码是相当人为的。$wuser当您开始寻找钥匙时,您知道这是错误的。所有引用都是正确的,因此错误的引用永远不能包含键。

  • 可以使用['no autovivification;`](http://search.cpan.org/perldoc?autovivification)来关闭/配置此行为。 (4认同)