使用未初始化的值
在运行Perl代码时,这是你最常碰到的警告之一。
这个警告不会终止脚本的执行,而且它只有在打开警告时才会出现。建议打开警告。
最常见打开警告的办法是在你的脚本或者模块开头包含use warnings;声明。
老的办法是在#!一行加上-w标志。通常脚本的第一行类似这样:
#!/usr/bin/perl -w
这其中有些区别,但是use warnings在12年前已经存在了,没必要不使用它。换句话说: 总是使用use warnings;!
我们回过头来看看实际的警告是什么意思。 Let's go back to the actual warning I wanted to explain.
简要解释
Use of uninitialized value $x in say at perl_warning_1.pl line 6.
这表明变量$x没有赋值(它的值是一个特殊值undef)。 或是从未被赋值,或是某个地方被赋了值undef。
你需要查找变量最后一次赋值的地方,或者试图发现为啥那段代码从未执行。
一个简单的例子
下边的例子会产生这种警告。
use warnings; use strict; use 5.010; my $x; say $x;
Perl会很体贴地告诉我们哪个文件的哪一行导致了这个警告。
仅仅一个警告
前边说过,这只是一个警告。如果脚本在say语句之后,还有更多的语句,他们将被执行:
use warnings; use strict; use 5.010; my $x; say $x; $x = 42; say $x;
这会打印
Use of uninitialized value $x in say at perl_warning_1.pl line 6. 42
打乱输出顺序
不过仍要小心,如果你的代码里,在产生警告的一行之前有打印语句,正如这个例子中那样:
use warnings; use strict; use 5.010; print 'OK'; my $x; say $x; $x = 42; say $x;
结果会比较令人困惑。
Use of uninitialized value $x in say at perl_warning_1.pl line 7. OK 42
这里,第一个say语句的结果,在警告之后出现,即便它在产生警告的代码之前被调用。
这个怪异现象源于IO缓存。默认情况下,Perl缓存标准输出,但是不缓存标准错误。
因此,单词'OK'在等待缓冲区刷新时,警告信息已经输出到屏幕了。
关闭缓冲
你可以关闭标准输出缓存以避免这种情况。
这可以在脚本开始处通过如下代码实现: $| = 1;
use warnings; use strict; use 5.010; $| = 1; print 'OK'; my $x; say $x; $x = 42; say $x;
OKUse of uninitialized value $x in say at perl_warning_1.pl line 7. 42
(警告跟OK出现在同一行,这是因为我们没有在OK之后打印一个新行符\n。)
不期望的作用域
use warnings; use strict; use 5.010; my $x; my $y = 1; if ($y) { my $x = 42; } say $x;
这段代码也会产生警告Use of uninitialized value $x in say at perl_warning_1.pl line 11.。
我曾多次犯过这种错误。都因为没注意到我在if代码块之内使用了my $x。
这意味着我创建了另一个变量$x并赋值为42,却想在代码块作用域之后继续使用。 ($y = 1只是个占位符用于模拟一些真实的代码或者一些真实的情况。这只是使这个例子更逼真。)
当然我们有需要在if代码块之内声明变量的情形,不过并不经常。而当我错误地这么做时,找bug就相当痛苦。

Published on 2013-05-01