die#
זריקת חריגה.
die זורק חריגה הבנויה מ־LIST. אם החריגה מתרחשת בתוך eval, ה־eval מסתיים עם undef ו־$@ מחזיק את ערך החריגה. אם דבר אינו תופס אותה, Perl מדפיס את ההודעה ל־STDERR והמפרש יוצא עם סטטוס שונה מאפס. החריגה יכולה להיות מחרוזת פשוטה, רשימה שמומרת למחרוזת, או הפניה - בדרך כלל עצם מבורך הנושא מצב שגיאה מובנה.
תקציר#
die LIST
die $message
die $exception_object
die # re-raise / propagate current $@
מה מוחזר#
die אינו חוזר. השליטה מועברת ל־eval הדינמי המקיף הקרוב ביותר (שמחזיר אז undef בהקשר סקלרי או רשימה ריקה בהקשר רשימה), או - אם אין eval מקיף - המפרש משחרר את המחסנית, מריץ את מטפלי END ו־DESTROY, ויוצא.
ערך החריגה עצמו נוחת ב־$@:
חריגות מחרוזת - ההודעה המומרת למחרוזת, כולל כל
at FILE line N.\nשצורף (ראו להלן).חריגות הפניה - ההפניה עצמה, ללא שינוי. זוהי הדרך האידיומטית לזרוק עצם חריגה מבורך.
ביציאה לא־תפוסה, קוד היציאה נגזר מ־$! ומ־$?:
exit $! if $!; # errno
exit $? >> 8 if $? >> 8; # child exit status
exit 255; # last resort
יש להסתמך רק על כך שקוד היציאה שונה מאפס; הערך המדויק הוא קידוד במאמץ־מירבי של כל מצב שגיאה גלובלי שהיה פעיל ברגע הזריקה.
מצב גלובלי שהוא נוגע בו#
$@- נכתב עם החריגה בשחרור המחסנית אלeval, נקרא על־ידי הצורה חסרת־הארגומנטים שלdieכדי להפיץ חריגה קיימת, ונקרא על־ידי מדפיס חריגות לא־תפוסות.$!- נקרא בעת גזירת קוד יציאה עבור חריגה לא־תפוסה, ובדרך כלל משובץ בתוך ההודעה עצמה (die "open $f: $!").$?- נקרא בעת גזירת קוד יציאה אם$!הוא אפס. מטפליENDו־DESTROYעדיין יכולים לשנות אותו לפני שהתהליך בפועל יוצא.$.- מספר שורת הקלט הנוכחית, מצורף לחריגות מחרוזת שחסר להן תו שורה חדשה מסיים.$SIG{__DIE__}- אם מוגדר, המטפל רץ לפני שהחריגה מופצת, עם החריגה כארגומנט שלו. המטפל יכול להחליף את החריגה על־ידי קריאה ל־dieשוב עם ערך שונה.$^S- קריא על־ידי מטפלי$SIG{__DIE__}כדי לדעת האם ה־die מתרחש בתוךeval.
כלל תו השורה החדשה המסיים#
האם die מצרף מידע מיקום תלוי בתו אחד בסוף ההודעה:
ההודעה מסתיימת ב־
"\n"- בשימוש מילולי. דבר אינו מצורף. יש להשתמש בצורה זו כאשר ההודעה היא כבר אבחנה שלמה הפונה למשתמש.ההודעה אינה מסתיימת ב־
"\n"- Perl מצרף" at FILE line N", ואם נקרא קובץ,", <HANDLE> line M", ואז"."מסיים ותו שורה חדשה. יש להשתמש בצורה זו במהלך פיתוח, או בכל פעם שאיתור קריאת ה־dieבמקור שימושי יותר מהודעה מסודרת.
die "bad config\n"; # "bad config\n"
die "bad config"; # "bad config at script.pl line 42.\n"
אידיום נפוץ הוא לצרף ", stopped" כדי לגרום לסיומת המיקום להיקרא באופן טבעי:
die "/etc/games is no good, stopped";
# /etc/games is no good, stopped at canasta line 123.
לחריגות הפניה לעולם לא מצורף מידע מיקום - המרת עצם למחרוזת כדי לבחון אותו תסכל את התכלית של זריקת עצם. אם רוצים קובץ ושורה בתוך חריגה מובנית, יש ללכוד אותם בזמן הבנייה (__FILE__, __LINE__, או caller).
חריגות בעלות ערך־הפניה#
העברת הפניה - בדרך כלל עצם מבורך - מאפשרת ל־$@ לשאת מצב מובנה במקום מחרוזת שיש לפרסר אותה אחר־כך:
package MyApp::Error;
sub new { my ($c, %a) = @_; bless { %a }, $c }
sub code { $_[0]{code} }
sub where { $_[0]{where} }
eval {
die MyApp::Error->new(code => 'EPARSE', where => 'line 12');
};
if (my $err = $@) {
if (ref($err) && $err->isa('MyApp::Error')) {
warn "parse error at ", $err->where;
}
else {
die $err; # not ours - re-raise
}
}
יש להעמיס את ההמרה למחרוזת על מחלקות החריגה כך שחריגה לא־תפוסה עדיין מדפיסה הודעה שימושית:
use overload '""' => sub { "[MyApp::Error ".$_[0]->code."]\n" };
הצורה המומרת למחרוזת צריכה להסתיים בתו שורה חדשה ולא להיות ריקה, בהתאמה לטיפול בחריגות מחרוזת.
מכיוון ש־$@ גלובלי, יש להעתיק אותו למשתנה לקסיקלי לפני בחינתו - כל קריאת מתודה, ref, או isa שמופעלים במהלך הטיפול יכולים בעצמם להפעיל eval פנימי ולדרוס את $@:
if (my $err = $@) { ... } # safe
if ($@) { $@->method; ... } # unsafe: method may reset $@
הפצה: die ללא ארגומנט (או מחרוזת ריקה)#
כאשר LIST ריקה או מומרת למחרוזת "", die אינו זורק חריגה חדשה - הוא זורק מחדש כל מה שנמצא ב־$@:
אם
$@מחזיק מחרוזת,dieמצרף"\t...propagated at FILE line N.\n"וזורק מחדש. זוהי הדרך הקנונית לתת לחריגה להמשיך במעלה מחסנית הקריאות לאחר בדיקת התאמה חלקית:eval { risky() }; die unless $@ =~ /Expected exception/;
אם
$@מחזיק הפניית עצם עם מתודהPROPAGATE, המתודה הזו נקראת כ־$@ = eval { $@->PROPAGATE(__FILE__, __LINE__) }, והערך המוחזר מחליף את$@לפני הזריקה מחדש. יש לממשPROPAGATEעל מחלקת חריגה כאשר רוצים שהחריגה תתעד את שרשרת הזריקות מחדש.אם
$@מחזיק הפניית עצם ללאPROPAGATE, ההפניה נזרקת מחדש ללא שינוי.אם גם
$@ריק, המחרוזת"Died"בשימוש.
הוו של $SIG{__DIE__}#
קביעת $SIG{__DIE__} מתקינה מטפל שרץ כאשר die נורה, עם החריגה כארגומנט שלו. המטפל יכול לבחון או להחליף את החריגה על־ידי קריאה ל־die שוב עם ערך שונה. הוא רץ גם בתוך eval, וזו הסיבה הרגילה לרצות אותו מהדרך:
local $SIG{__DIE__} = sub {
die @_ if $^S; # inside eval: do nothing special
log_fatal(@_); # outside eval: log before we exit
};
$^S הוא undef במהלך הידור, אמת בתוך eval, ושקר ברמה העליונה - יש להשתמש בו כדי לשעֵר עבודת מטפל שמשמעותית רק עבור חריגות לא־תפוסות.
דוגמאות#
יציאה מהירה עם הודעה נקייה (שימו לב שתו השורה החדשה המסיים מדכא את צירוף הקובץ/שורה):
chdir '/var/spool' or die "can't cd to spool: $!\n";
die ללא תו שורה חדשה במהלך פיתוח כך שהמיקום מצורף:
die "unexpected empty record";
# unexpected empty record at parse.pl line 87.
תפיסת חריגת מחרוזת:
eval {
parse($input);
};
if ($@) {
warn "parse failed: $@"; # $@ already ends in "\n" if the
# die'd message did
}
זריקה ותפיסה של עצם חריגה מבורך:
eval {
die MyApp::Error->new(code => 'EIO', detail => $!);
};
if (my $err = $@) {
if (ref($err) && $err->isa('MyApp::Error')) {
handle($err);
}
else {
die $err; # re-raise anything unexpected
}
}
הפצה מותנית - לתפוס מחלקה אחת, לתת לשאר לעבור:
eval { work() };
die unless $@ =~ /^recoverable:/;
recover();
מקרי קצה#
רשימה עם שני פריטים או יותר מומרת למחרוזת ומשורשרת לכדי ההודעה:
die "read failed on ", $file, ": $!". כלל תו השורה החדשה חל על התוצאה המשורשרת.רשימה ריקה (
die;אוdie "";) מפעילה את מסלול ההפצה המתואר לעיל, לא חריגה חדשה.הפניה עם תו שורה חדשה מסיים בתוך הצורה המומרת למחרוזת אינה רלוונטית: מיקום לעולם לא מצורף להפניה, ללא קשר למה שההעמסה
""שלה מפיקה.dieבתוךDESTROYבמהלך השמדה גלובלית עדיין יכול לירות את$SIG{__DIE__}אך עלול לא להתפשט כצפוי - המפרש כבר משחרר את המחסנית. יש לשמור על הורסים מתגוננים.dieלא־תפוס במהלך בלוקENDמריץ את שאר בלוקיENDאך קובע סטטוס יציאה לפי כלל$!/$?לעיל.evalמקונן ו־$SIG{__DIE__}: המטפל רץ עבור כל die, כולל אלו הנתפסים על־ידיevalפנימי. יש להגן עם$^Sאם למטפל יש תופעות לוואי.זריקה מחדש של
$@הנוכחי: עדיףdie;חשוף על־פניdie $@;. הצורה החשופה מפעילה את מנגנון ההפצה (סיומת...propagated, הווPROPAGATE);die $@לא - הוא מתייחס ל־$@כערך חריגה חדש.
הבדלים מהמעלה־הזרם#
תאימות מלאה עם Perl 5.42 מהמעלה־הזרם.
ראו גם#
eval- המבנה היחיד שתופסdie; צורת הבלוק שלו לוכדת חריגות אל$@warn- אותם כללי פורמט (תו שורה חדשה מסיים מדכא את המיקום), אך כותב ל־STDERRואינו משחרר את המחסניתcaller- לכידת קובץ ושורה בזמן הזריקה בעת בניית עצם חריגה מובנהexit- לשימוש כאשר רוצים קוד יציאה מסוים ללא מנגנון טיפול החריגות$@- היכן שהחריגה נוחתת לאחר ש־evalתופס אותה, והמקור ש־dieחסר־הארגומנט זורק מחדש ממנו$SIG{__DIE__}- הוו טרום־זריקה שיכול לבחון או לשכתב את החריגה