内容

名称

Carp - 模块的替代 warn 和 die

概要

use Carp;

# warn user (from perspective of caller)
carp "string trimmed to 80 chars";

# die of errors (from perspective of caller)
croak "We're outta here!";

# die of errors with stack backtrace
confess "not implemented";

# cluck, longmess and shortmess not exported by default
use Carp qw(cluck longmess shortmess);
cluck "This is how we got here!"; # warn with stack backtrace
my $long_message   = longmess( "message from cluck() or confess()" );
my $short_message  = shortmess( "message from carp() or croak()" );

描述

Carp 例程在您自己的模块中很有用,因为它们的行为类似于 die()warn(),但消息更有可能对您的模块用户有用。在 cluck()confess() 的情况下,该上下文是调用堆栈中每个调用的摘要;longmess() 返回错误消息的内容。

对于更短的消息,您可以使用 carp()croak(),它们将错误报告为来自调用您的模块的位置。shortmess() 返回此错误消息的内容。不能保证这就是错误发生的位置,但这是一个很好的猜测。

Carp 在组装错误消息的过程中,会小心地避免覆盖状态变量 $!$^E。这意味着,如果需要增强错误消息,并且调用 Carp 的代码在这些变量中留下了有用的值,那么 $SIG{__DIE__}$SIG{__WARN__} 处理程序可以捕获这些变量中保存的错误信息。当然,Carp 无法保证后者。

您还可以通过更改 Carp 命名空间中的一些全局变量来更改 Carp 的输出和逻辑方式。请参阅下面关于 "全局变量" 的部分。

以下是关于 carpcroak 工作原理的更完整描述。它们的工作原理是在调用堆栈中搜索函数调用堆栈,直到找到一个没有被告知不应该出现错误的调用堆栈。如果所有调用都被标记为安全,它们就会放弃并返回完整的堆栈回溯。换句话说,它们假设第一个看起来像潜在嫌疑人的调用就是罪魁祸首。它们用于判断调用是否不应该生成错误的规则如下:

  1. 任何来自包到自身的调用都是安全的。

  2. 包声明,对包含在 @CARP_NOT 中的包或(如果该数组为空)@ISA 中的包的调用不会出现错误。覆盖 @ISA 的能力是 5.8 中的新功能。

  3. 第 2 项中的信任是可传递的。如果 A 信任 B,B 信任 C,那么 A 也信任 C。因此,如果您没有使用 @CARP_NOT 覆盖 @ISA,那么这种信任关系就等同于“继承自”。

  4. 任何来自内部 Perl 模块的调用都是安全的。(没有什么可以阻止用户模块将自己标记为 Perl 的内部模块,但这种做法不建议。)

  5. 任何对 Perl 的警告系统的调用(例如 Carp 本身)都是安全的。(这条规则可以防止它在您调用 carpcroak 的地方报告错误。)

  6. $Carp::CarpLevel 可以设置为跳过固定数量的额外调用级别。不建议使用此方法,因为它很难让它正常工作。

强制堆栈回溯

作为调试辅助工具,您可以强制 Carp 将所有模块的 croak 视为 confess,将 carp 视为 cluck。换句话说,强制提供详细的堆栈回溯。这在尝试理解警告或错误的生成原因或位置时非常有用。

此功能通过“导入”不存在的符号“verbose”来启用。您通常可以通过以下方式启用它:

perl -MCarp=verbose script.pl

或者在 PERL5OPT 环境变量中包含字符串 -MCarp=verbose

或者,您可以将全局变量$Carp::Verbose设置为 true。请参阅下面的"全局变量"部分。

堆栈跟踪格式

在每个堆栈级别,子例程的名称与其参数一起显示。对于简单的标量,这已经足够了。对于复杂的数据类型,例如对象和其他引用,这可能只显示'HASH(0x1ab36d8)'

Carp 提供了两种方法来控制这一点。

  1. 对于对象,如果存在,将调用方法CARP_TRACE。如果此方法不存在,或者它递归到Carp,或者它以其他方式抛出异常,则跳过此步骤,Carp 继续执行下一个选项,否则检查停止,并使用返回的字符串。建议对象类型是字符串的一部分,以方便调试。

  2. 对于任何类型的引用,都会检查$Carp::RefArgFormatter(见下文)。此变量应为代码引用,并将传入当前参数。如果此函数不存在(变量为 undef),或者它递归到Carp,或者它以其他方式抛出异常,则跳过此步骤,Carp 继续执行下一个选项,否则检查停止,并使用返回的字符串。

  3. 否则,如果CARP_TRACE$Carp::RefArgFormatter均不可用,则忽略任何重载,将值转换为字符串。

全局变量

$Carp::MaxEvalLen

此变量决定在输出中显示多少个字符串评估字符。使用值0显示所有文本。

默认值为0

$Carp::MaxArgLen

此变量决定打印每个函数参数的字符数。使用值0显示参数的完整长度。

默认值为64

$Carp::MaxArgNums

此变量决定显示每个函数的多少个参数。使用假值显示函数调用中的所有参数。要抑制所有参数,请使用-1'0 but true'

默认值为8

$Carp::Verbose

此变量使carp()croak()生成堆栈回溯,就像cluck()confess()一样。这就是use Carp 'verbose'在内部实现的方式。

默认值为0

$Carp::RefArgFormatter

此变量设置一个通用的参数格式化程序来显示引用。简单的标量和实现了 CARP_TRACE 的对象不会经过此格式化程序。不支持从该函数内部调用 Carp

local $Carp::RefArgFormatter = sub {
    require Data::Dumper;
    Data::Dumper->Dump($_[0]); # not necessarily safe
};

@CARP_NOT

此变量,在您的包中,表示哪些包被视为错误的位置。carp()cluck() 函数在报告错误发生位置时会跳过调用者。

注意:此变量必须在包的符号表中,因此

# These work
our @CARP_NOT; # file scope
use vars qw(@CARP_NOT); # package scope
@My::Package::CARP_NOT = ... ; # explicit package variable

# These don't work
sub xyz { ... @CARP_NOT = ... } # w/o declarations above
my @CARP_NOT; # even at top-level

使用示例

package My::Carping::Package;
use Carp;
our @CARP_NOT;
sub bar     { .... or _error('Wrong input') }
sub _error  {
    # temporary control of where'ness, __PACKAGE__ is implicit
    local @CARP_NOT = qw(My::Friendly::Caller);
    carp(@_)
}

这将使 Carp 报告错误来自不在 My::Carping::PackageMy::Friendly::Caller 中的调用者。

另请阅读上面的 "DESCRIPTION" 部分,了解 Carp 如何决定从哪里报告错误。

使用 @CARP_NOT,而不是 $Carp::CarpLevel

覆盖 Carp@ISA 的使用。

%Carp::Internal

这表示哪些包是 Perl 的内部包。Carp 永远不会将错误报告为来自 Perl 内部包中的行。例如

$Carp::Internal{ (__PACKAGE__) }++;
# time passes...
sub foo { ... or confess("whatever") };

将从第一个不在 __PACKAGE__ 中的调用者开始提供完整的堆栈回溯。(除非该包也是 Perl 的内部包。)

%Carp::CarpInternal

这表示哪些包是 Perl 警告系统的内部包。对于生成完整的堆栈回溯,这与 Perl 内部相同,堆栈回溯不会从列在 %Carp::CarpInternal 中的包内部开始。但对于 carpcroak 生成的摘要消息来说,它略有不同。这些错误不会在调用 %Carp::CarpInternal 中的包的任何行上报告。

例如,Carp 本身列在 %Carp::CarpInternal 中。因此,confess 的完整堆栈回溯不会从 Carp 内部开始,并且调用 croak 的简短消息不会放在调用 croak 的行上。

$Carp::CarpLevel

此变量决定在报告错误发生在调用 Carp 函数时跳过多少个额外的调用帧,这些调用帧在其他情况下不会被跳过。在生成完整堆栈回溯的调用中计算这些调用帧相当容易。但是,对于生成简短消息的调用,进行此类计算要困难得多。通常人们会跳过太多调用帧。如果他们幸运的话,他们跳过的调用帧足够多,以至于 Carp 会遍历整个调用堆栈,意识到有错误,然后生成完整的堆栈回溯。如果他们不幸的话,错误将从调用堆栈中非常高的误导性位置报告。

因此,最好避免使用 $Carp::CarpLevel。而是使用 @CARP_NOT%Carp::Internal%Carp::CarpInternal

默认值为0

BUGS

Carp 例程目前不处理异常对象。如果以第一个参数为引用调用,它们将简单地调用 die() 或 warn(),具体取决于情况。

SEE ALSO

Carp::AlwaysCarp::Clan

CONTRIBUTING

Carp 由 perl 5 维护者维护,作为核心 perl 5 版本控制库的一部分。请参阅 perlhack perldoc,了解如何提交补丁并为其做出贡献。

AUTHOR

Carp 模块首次出现在 Larry Wall 的 perl 5.000 发行版中。从那时起,它被几个 perl 5 维护者修改过。Andrew Main (Zefram) <[email protected]> 将 Carp 分离成一个独立的发行版。

COPYRIGHT

Copyright (C) 1994-2013 Larry Wall

Copyright (C) 2011, 2012, 2013 Andrew Main (Zefram) <[email protected]>

LICENSE

此模块是免费软件;您可以根据与 Perl 本身相同的条款重新分发和/或修改它。