我正在研究Webmin的source code。
($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.
}
所以...什么时候以及如何undef变量变成{}而没有任何定义...
答案 0 :(得分:8)
这里的问题是Perl功能,称为“自动生存”。基本上,这意味着,如果将未定义的Perl变量视为引用类型,则Perl将创建该类型的引用并将其存储在变量中。
因此,当您执行以下语句时,您的问题就开始了:
if ($wuser->{'pass'} eq 'x')
Perl认为您将$wuser
视为哈希引用,因此它将创建一个空哈希并将该哈希的引用存储在$wuser
中。然后,它可以在该哈希中查找“ pass”键,并发现它不存在。
通常,这被视为一项功能。您可以运行以下代码:
my $hash; # created as undef
$hash->{foo}{bar}{baz} = 1;
Perl将为您创建此数据结构:
{
'foo' => {
'bar' => {
'baz' => 1
}
}
};
您无需费心创建哈希的所有中间级别。
当然,您的代码是人为的。您知道开始寻找密钥时$wuser
为假。所有引用都是正确的,因此错误的引用永远不能包含键。