內容

名稱

Carp - 模組的替代警告和 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。這表示 $SIG{__DIE__}$SIG{__WARN__} 處理常式可以在這些變數中擷取錯誤資訊(如果需要擴充錯誤訊息,且呼叫 Carp 的程式碼在那裡留下有用的值)。當然,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(請參閱下方)。預期此變數為程式碼參考,並傳入目前的參數。如果此函式不存在(變數未定義),或者它遞迴進入 Carp,或者它會擲出例外,則會略過此函式,而 Carp 會繼續執行下一個選項,否則會停止檢查並使用傳回的字串。

  3. 否則,如果 CARP_TRACE$Carp::RefArgFormatter 都不可用,則會將值字串化,並忽略任何重載。

全域變數

$Carp::MaxEvalLen

此變數會決定在輸出中要顯示字串評估的字元數。使用值 0 來顯示所有文字。

預設為 0

$Carp::MaxArgLen

此變數會決定要列印函式每個引數的字元數。使用值 0 來顯示引數的完整長度。

預設為 64

$Carp::MaxArgNums

此變數會決定要顯示每個函式的引數數。使用 false 值來顯示函式呼叫的所有引數。若要抑制所有引數,請使用 -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

錯誤

Carp 常式目前無法處理例外物件。如果呼叫時第一個引數是參考,則它們會適當地呼叫 die() 或 warn()。

另請參閱

Carp::AlwaysCarp::Clan

貢獻

Carp 由 perl 5 協力廠商維護,作為核心 perl 5 版本控制儲存庫的一部分。請參閱 perlhack perldoc,了解如何提交修補程式並貢獻其中。

作者

Carp 模組首次出現在 Larry Wall 的 perl 5.000 發行版中。從那時起,它已被多位 perl 5 協力廠商修改。Andrew Main (Zefram) <zefram@fysh.org> 將 Carp 分離成一個獨立的發行版。

版權

版權所有 (C) 1994-2013 Larry Wall

版權所有 (C) 2011、2012、2013 Andrew Main (Zefram) <zefram@fysh.org>

授權

此模組是免費軟體;您可以在與 Perl 相同的條款下重新分發或修改它。