בחינת מצב#
פרק זה מכסה את אוצר המילים של מנפה השגיאות לבחינת נתונים: x, V, X, y, m, M, i, והאפשרויות השולטות בעומק שבו מבוצע dump לערכים מצרפיים. לאחר פרק זה תוכלו לשאול כל תוכנית רצה ״איך המשתנה הזה, החבילה הזו, העצם הזה באמת נראים כרגע?״
קוראים מגיעים לכאן בידיעה ש־p EXPR מדפיס סקלר. שאר פקודות הבחינה מצדיקות את עצמן ברגע שהתשובה ל־״מה זה?״ דורשת יותר מערך יחיד.
x: dump של מבנים#
x EXPR מבצע הדפסה מסודרת בהקשר רשימה, ויורד רקורסיבית להפניות:
DB<1> x \%config
0 HASH(0x5651f9a82358)
'debug' => 1
'dsn' => 'dbi:SQLite::memory:'
'timeout' => 30
'users' => ARRAY(0x5651f9b28a10)
0 'alice'
1 'bob'
2 'carol'
תמיד העבירו הפניה עבור ערכים מצרפיים. x %h מבצע dump לרשימת מפתח/ערך שטוחה, אשר מסתירה את המבנה. x \%h עושה את מה שאתם רוצים.
DB<2> x \@list
0 ARRAY(0x5651f9b28a10)
0 'alice'
1 'bob'
2 'carol'
DB<3> x $obj
0 MY::Class=HASH(0x5651fa01c2b0)
'id' => 42
'prefs' => HASH(0x5651fa01c330)
'theme' => 'dark'
עבור מבנים עמוקים או מחזוריים, הגבילו את הרקורסיה:
DB<4> x 2 \%tree # recurse 2 levels deep
DB<5> x 1 $obj # one level
אם הטוקן הראשון של הביטוי הוא מספרי, השתמשו בסוגריים:
DB<6> x (3 + $offset) # without parens, 3 is mis-parsed as depth
V ו־X: משתני חבילה#
V [PKG [VARS]] מבצע dump לגלובלים של חבילה:
DB<1> V main
$counter = 42
@ARGV = (
0 '--verbose'
1 'input.txt'
)
%ENV = (
'PATH' => '/usr/bin:/bin'
...
)
עם ארגומנט שני, סננו משתנים:
DB<2> V MyApp $config $last_user # only these
DB<3> V MyApp ~^config # regex: names matching /^config/
DB<4> V MyApp !^_ # regex: names NOT matching /^_/
X הוא V עבור החבילה הנוכחית:
DB<5> X # dump current package's globals
DB<6> X $foo @bar # filtered
V / X לא רואים לקסיקלים (משתני my). עבור אלה, השתמשו ב־y.
y: לקסיקלים בתחום העוטף#
y LEVEL [VARS] קורא משתני my לקסיקליים דרך PadWalker:
DB<1> y 0 # lexicals of the current sub
my $req = HTTP::Request=HASH(0x...)
my $user_id = 42
my @errors = ()
DB<2> y 1 # one frame up (the caller's lexicals)
my $request_count = 118
my $dispatcher = MyApp::Dispatcher=HASH(0x...)
DB<3> y 0 $req $user_id # only those
y דורש את PadWalker בגרסה 0.08 או חדשה יותר. הוא עובד רק בתוך sub (לגוף הסקריפט החיצוני אין pad לעבור עליו).
m: מתודות של עצם או מחלקה#
m EXPR מפרט מתודות שניתן לקרוא להן על עצם או מחלקה:
DB<1> m $user
via UNIVERSAL: isa can DOES VERSION DESTROY
via MyApp::Model: save load delete update
via MyApp::Role::Auditable: audit_log record_event
DB<2> m 'MyApp::Worker'
via UNIVERSAL: ...
via MyApp::Worker: dispatch retry cancel
מקבץ מתודות לפי החבילה שמספקת אותן - שימושי לאיתור איזה תפקיד או על־מחלקה מספקים מתודה.
M ו־i: מודולים וירושה#
M מפרט מודולים טעונים עם גרסאות:
DB<1> M
'DBI' (version 1.643)
'JSON::PP' (version 4.16)
'MyApp::Model' (version undef)
...
i CLASS או i $obj מדפיס את עץ הירושה:
DB<2> i $user
MyApp::User 0.12
MyApp::Model 0.42
Moo::Object ?
שימושי עבור ״מאיפה המתודה הזו באמת מגיעה?״ כאשר רזולוציית המתודה חוצה מספר תפקידים.
S: שמות תתי־שגרות#
S [[!]PAT] מפרט שמות sub התואמים (או שאינם תואמים) לתבנית:
DB<1> S ^MyApp::Worker::
MyApp::Worker::cancel
MyApp::Worker::dispatch
MyApp::Worker::retry
DB<2> S !^(main|DB|UNIVERSAL):: # everything except these
S לבדו מפרט הכל - ארוך.
p מול x: במה להשתמש מתי#
רוצים | השתמשו |
|---|---|
ערך של סקלר יחיד, פשוט |
|
ביטוי מצורף / מפורמט |
|
hash או מערך |
|
שדות של עצם |
|
רק הרמה העליונה |
|
משתני חבילה של |
|
לקסיקלים של ה־sub הנוכחי |
|
רשימת המתודות של |
|
שרשרת ה־ |
|
מקרה מיוחד: p הוא הדפסה שטוחה. עבור הפניה, p $ref מדפיס HASH(0x…). השתמשו ב־x $ref עבור התוכן.
אפשרויות עומק וקומפקטיות#
פלט ה־dump מעוצב על־ידי אפשרויות הנקבעות באמצעות הפקודה o. ההגדרות הרלוונטיות לבחינה:
אפשרות | השפעה |
|---|---|
| עומק רקורסיה (שלילי = ללא הגבלה). ברירת מחדל 4. |
| N האלמנטים הראשונים של המערך בלבד; ריק = הכל. |
| אותו דבר, עבור hashes. |
| מערכים קצרים בשורה אחת. |
| הדוק עוד יותר. |
| dump של תוכן glob. |
| הרחבה מלאה של הפניות חוזרות (היזהרו ממחזורים). |
|
|
| כיצד |
| הדפסה של הצורה הממורצת על־ידי overload. |
קביעת אפשרות בסשן:
DB<1> o dumpDepth=6
DB<2> o compactDump=1
DB<3> o arrayDepth=20
DB<4> o compactDump? # query current value
קביעת אפשרויות באתחול באמצעות PERLDB_OPTS או ב־.perldb:
PERLDB_OPTS="dumpDepth=6 compactDump=1" perl -d script.pl
בחינת ה־internals של SV#
Devel::Peek חושף את האחסון הפנימי של הסקלר - type flags, refcount, פריסת PV/NV/IV, שרשרת magic - כאשר השאלה היא ״איזה סוג סקלר זה באמת?״:
DB<1> use Devel::Peek; Dump($sv)
בעיקר לחקירת משתנים קשורים, עצמים בעלי overloading, או חריגות ביצועים שבהן התשובה תלויה האם סקלר מאוחסן כרגע כמספר שלם, כמחרוזת, או כשניהם.
שימו לב: Devel::Peek ב־pperl הוא שכבת תאימות - הוא מדווח על פריסת Sv ספציפית ל־pperl במקום פריסת SV של perl5. לשדות כמו REFCNT, FLAGS, PV, IV, NV יש מקבילים; הפלט המדויק שונה. ראו את מדריך הארכיטקטורה של pperl לפרטי הפריסה.
הערכה ב־prompt#
כל דבר שאינו מזוהה כפקודה מוערך כ־Perl. השתמשו בכך כדי לחקור עמוק יותר מאשר פקודה יחידה:
DB<1> p keys %{ $obj->{prefs} }
theme,locale,tz
DB<2> x [ grep { !defined $_->{parent} } @nodes ]
DB<3> x { map { $_->id => $_->name } @users }
עבור assertions חד־פעמיים ללא עצירה:
DB<1> die "unexpected" if ref $obj ne 'MyApp::User'
I/O של תוכנית מול I/O של מנפה השגיאות#
הקלט והפלט של מנפה השגיאות עוברים דרך $DB::IN ו־$DB::OUT, אשר פתוחים אל /dev/tty ישירות. התוכנית יכולה להפנות מחדש STDIN / STDOUT / STDERR בחופשיות; ה־prompt של מנפה השגיאות עדיין מופיע. בכיוון ההפוך, פלט p EXPR אינו מזהם את ה־stdout הנלכד של התוכנית.
למידע נוסף#
breakpoints - לעצור היכן שניתן לבחון; פרק זה הוא על מה לבחון לאחר שעוצרים.
tracing - לצפות בערכים משתנים לאורך זמן מבלי לעצור בכל צעד.