die
引发异常。在 eval
内部,异常被塞入 $@
,并且 eval
以未定义的值终止。如果异常位于所有封闭 eval
之外,则未捕获的异常将打印到 STDERR
,并且 perl 将退出,退出代码表示失败。如果你需要使用特定退出代码退出进程,请参见 exit
。
等效示例
die "Can't cd to spool: $!\n" unless chdir '/usr/spool/news';
chdir '/usr/spool/news' or die "Can't cd to spool: $!\n"
大多数情况下,die
被调用时带有用作异常的字符串。你可以提供一个非引用操作数作为异常,或者提供一个包含两个或更多项的列表,这些项将被字符串化并连接起来以构成异常。
如果字符串异常没有以换行符结尾,则当前脚本行号和输入行号(如果有)以及换行符将附加到它。请注意,“输入行号”(也称为“块”)受当前生效的“行”概念的影响,并且也可以作为特殊变量 $.
获得。请参见 "$/" in perlvar 和 "$." in perlvar。
提示:有时在字符串“at foo line 123”附加后,将“, stopped”
附加到消息中会使其更有意义。假设您正在运行脚本“canasta”。
die "/etc/games is no good";
die "/etc/games is no good, stopped";
分别产生
/etc/games is no good at canasta line 123.
/etc/games is no good, stopped at canasta line 123.
如果 LIST 为空或生成空字符串,并且 $@
已包含异常值(通常来自先前的 eval
),则在附加 "\t...propagated"
后会重用该值。这对于传播异常很有用
eval { ... };
die unless $@ =~ /Expected exception/;
如果 LIST 为空或生成空字符串,并且 $@
包含具有 PROPAGATE
方法的对象引用,则将使用附加的文件和行号参数调用该方法。返回值替换 $@
中的值;即,就像调用 $@ = eval { $@->PROPAGATE(__FILE__, __LINE__) };
一样。
如果 LIST 为空或生成空字符串,并且 $@
也为空,则使用字符串 "Died"
。
您还可以使用引用参数调用 die
,如果这在 eval
中被捕获,则 $@
包含该引用。这允许使用维护异常任意状态的对象进行更精细的异常处理。这种方案有时比使用正则表达式匹配 $@
的特定字符串值更可取。
由于 Perl 在显示之前会将未捕获的异常消息字符串化,因此您可能希望对异常对象重载字符串化操作。有关该主题的详细信息,请参阅 overload。为了符合字符串异常的处理方式,字符串化消息应为非空,并以换行符结尾。此外,由于无法在不销毁异常对象引用情况下对其进行字符串化,因此 Perl 不会尝试将位置或其他信息附加到引用异常。如果您想要具有复杂异常对象的定位信息,则必须安排将定位信息自行放入对象中。
由于 $@
是全局变量,因此请小心,分析由 eval
捕获的异常不会替换全局变量中的引用。在进行任何操作之前,最简单的方法是创建引用的本地副本。以下是一个示例
use Scalar::Util "blessed";
eval { ... ; die Some::Module::Exception->new( FOO => "bar" ) };
if (my $ev_err = $@) {
if (blessed($ev_err)
&& $ev_err->isa("Some::Module::Exception")) {
# handle Some::Module::Exception
}
else {
# handle all other possible exceptions
}
}
如果未捕获的异常导致解释器退出,则退出代码由 $!
和 $?
的值确定,伪代码如下
exit $! if $!; # errno
exit $? >> 8 if $? >> 8; # child exit status
exit 255; # last resort
与 exit
一样,$?
在展开调用堆栈之前设置;然后,任何 DESTROY
或 END
处理程序都可以更改此值,从而更改 Perl 的退出代码。
目的是将尽可能多的可能原因信息压缩到系统退出代码的有限空间中。但是,由于 $!
是 C 的 errno
的值,它可以被任何系统调用设置,这意味着 die
使用的退出代码的值是不可预测的,因此不应该依赖它,除了它是非零之外。
您可以通过设置 $SIG{__DIE__}
钩子,安排在 die
执行其操作之前运行回调。关联的处理程序被调用,异常作为参数,并且可以通过再次调用 die
来更改异常(如果它认为合适的话)。有关设置 %SIG
条目的详细信息,请参见 "perlvar 中的 %SIG",有关一些示例,请参见 eval
。虽然此功能仅在您的程序退出之前运行,但目前并非如此:$SIG{__DIE__}
钩子当前甚至在 eval
块/字符串中也被调用!如果希望钩子在这种情况下不执行任何操作,请将
die @_ if $^S;
作为处理程序的第一行(参见 "perlvar 中的 $^S")。因为这会促进奇怪的远距离动作,所以这种违反直觉的行为可能会在未来的版本中得到修复。