2014-04-04 21 views
10

我一直在研究一个CPAN模块的分支,该分支现在没有维护(据我所知)。在这个模块中,他们使用[email protected]来向堆栈传递错误消息。换句话说,如果在调用子程序时出现任何错误,他们会设置[email protected],并在调用之后检查它是否已设置。我从来没有见过这个变量,但我认为它很有用,所以我开始在代码中使用它。现在我最近读了一些关于它的内容,发现它的目的比这个窄一点。阅读perlvar(和其他关于此事的SO问题)并没有完全回答这个问题,但是,这样可以使用[email protected]吗?我知道的一些“标点符号”变量肯定应该用而不是以这种通用的方式使用(有些甚至与local),这是这种情况之一,还是我可以继续这种做法?

回答

1

[email protected]是Perl中一个相对“非特殊”的特殊变量。 Perl中没有任何内容从[email protected]中读取,并且最后只能由eval {}块写入。这使得它可以相对安全地用于您自己的错误指示。

特别是模块的核心IO::Socket树这是用来表示从构造失败:

use IO::Socket::IP; 
my $sock = IO::Socket::IP->new(...) or die "Cannot connect - [email protected]"; 

比较传统的$!不适合这里,因为$!具有魔力,包裹的libc级errno结构;这意味着它只能设置为一个整数errno值,即使它可以被读作一个数字或一个字符串。因为有些故障可能发生,并不直接涉及errno的值(在IO::Socket的情况下,例如多种解析器故障),有时$!对此不适合。

4

[email protected]通常不明确设置。相反,它会在发生异常时自动为您设置。从perldoc die

  • 模具LIST

    die抛出一个例外。在eval内部,错误消息填入[email protected],并且eval以未定义的值终止。如果该异常不在所有内附的eval之内,则未捕获的异常将LIST打印到STDERR,并以非零值退出。如果您需要退出具有特定退出代码的流程,请参阅exit

例如,

#!/usr/bin/perl 

eval { 
    print "Hi\n"; 
    die "Something went wrong here"; 
    print "Bye\n"; 
}; 
print [email protected]; 

打印

Hi 
Something went wrong here at ./cr22854919 line 5. 

它允许使用[email protected]传递错误消息在栈中向上以这种方式,作为一种试戴捕获机制。但是,由于它是一个全局变量,因此应在eval { }块之后尽快处理它,以确保其他代码不会干扰处理异常。


另一魔术变量通常用于错误处理是$!,其在C.就像errno

实施例:

my $path = "/tmp/no-such-file"; 
open F, '<', $path 
    or print STDERR "$path: $!\n"; 

输出:

/tmp/no-such-file: No such file or directory