Preflight: σύλληψη σφαλμάτων πριν τον χρόνο εκτέλεσης#
Αυτό το κεφάλαιο καλύπτει τις pragmas, τους ελέγχους κατά τη μεταγλώττιση, και τις ρυθμίσεις υγιεινής χρόνου εκτέλεσης που εμποδίζουν τα περισσότερα σφάλματα να φτάσουν καν στον αποσφαλματωτή. Ένα καθαρό preflight είναι ο συντομότερος δρόμος για σύντομη συνεδρία αποσφαλμάτωσης.
Οι αναγνώστες που ήδη γράφουν use v5.36 ή νεότερη τρέχουν εξ ορισμού υπό strict και warnings και μπορούν να μεταβούν απευθείας στις ενότητες διαγνωστικών και autoflush. Το υπόλοιπο του κεφαλαίου υποθέτει ότι ενδέχεται να συντηρείτε παλαιότερο κώδικα όπου ούτε το ένα ούτε το άλλο είναι σιωπηρά ενεργό.
Strict και warnings#
Από την Perl 5.36, το use v5.36; (και οποιαδήποτε δήλωση μεγαλύτερης έκδοσης) ενεργοποιεί σιωπηρά τα use strict; και use warnings;. Τα σύγχρονα σενάρια δεν γράφουν αυτές τις γραμμές - η δήλωση έκδοσης καλύπτει και τα δύο:
use v5.40;
Το use strict αρνείται τρεις κλάσεις πρόχειρου κώδικα κατά τη μεταγλώττιση: αδήλωτες μεταβλητές (strict vars), συμβολικές αναφορές (strict refs), και barewords που χρησιμοποιούνται ως συμβολοσειρές (strict subs). Το use warnings ενεργοποιεί διαγνωστικά χρόνου εκτέλεσης για αναγνώσεις από μη αρχικοποιημένες τιμές, αριθμητικές μετατροπές με απώλειες, χρήση filehandles μετά το κλείσιμό τους, και αρκετές δεκάδες άλλα αιχμηρά άκρα.
Παλαιωμένος κώδικας που δεν χρησιμοποιεί κανένα από τα δύο επωφελείται και από τα δύο: προσθέστε τα, διορθώστε τα σύμβολα για τα οποία παραπονούνται, κάντε commit.
Στενές εξαιρέσεις παραμένουν χρήσιμες:
no strict 'refs'; # genuine symbolic deref
no warnings 'uninitialized'; # known-safe defaulting
no warnings 'experimental::try'; # on 5.36, 5.38 - see below
Ποτέ μη απενεργοποιείτε γενικά: το no warnings; χωρίς λίστα κατηγοριών είναι σχεδόν πάντα λάθος.
Προαγωγή προειδοποιήσεων σε μοιραίες για μια περιοχή:
local $SIG{__WARN__} = sub { die $_[0] };
Χρήσιμο στην κορυφή του προγράμματος κατά την ανάπτυξη· η πρώτη προειδοποίηση γίνεται κατάρρευση που παράγει ίχνος στοίβας.
use diagnostics#
Επεκτείνει κάθε προειδοποίηση ή μοιραίο μήνυμα στην πλήρη παράγραφο από το perldiag:
use diagnostics;
Η έξοδος είναι φλύαρη - πολύ φλύαρη για παραγωγή - αλλά κατά την αποσφαλμάτωση εξηγεί τι σημαίνει στην πραγματικότητα ένα λιτό μήνυμα όπως «Odd number of elements in hash assignment» και πώς να το διορθώσετε.
Εκ των υστέρων εκδοχή: σωληνώστε το stderr ενός προγράμματος μέσω της εντολής splain για να σχολιάσετε προειδοποιήσεις εκ των υστέρων.
Έλεγχοι κατά τη μεταγλώττιση#
Το perl -c script.pl αναλύει το σενάριο και τρέχει κάθε BEGIN / use, μετά σταματάει πριν την πρώτη δήλωση χρόνου εκτέλεσης. Ένα καθαρό -c σημαίνει ότι το αρχείο και οι εξαρτήσεις του μεταγλωττίζονται· δεν σημαίνει ότι το πρόγραμμα τρέχει σωστά.
perl -c script.pl
script.pl syntax OK
Συνδυάστε με -w για να ενεργοποιήσετε καθολικά τις warnings για τη φάση μεταγλώττισης και κάθε κώδικα κατά τη μεταγλώττιση:
perl -cw script.pl
Το perl -MO=Deparse script.pl εκτυπώνει αυτό που πραγματικά ανέλυσε η perl - λάθος αναλύσεις προτεραιότητας, κλάδους που πτυχώθηκαν σε σταθερές, for που ξαναγράφτηκε ως while. Χρησιμοποιήστε το για να επαληθεύσετε ότι η perl είδε αυτό που εννοούσατε:
perl -MO=Deparse script.pl
Το perl -MO=Deparse,-p επιβάλλει πλήρη παρενθεσιοποίηση και κάνει την προτεραιότητα ρητή.
Το perl -MO=Concise script.pl εκτυπώνει συμπαγές dump του δέντρου op· κυρίως για αναγνώστες που κάνουν εργασία βαθιάς βελτιστοποίησης.
autodie: κάντε την αποτυχία να εκτοξεύει#
Οι ενσωματωμένες που σηματοδοτούν αποτυχία μέσω ψευδών τιμών επιστροφής (open, close, chdir, unlink) είναι εύκολο να ξεχάσετε να ελέγξετε. Το autodie τις αντικαθιστά με εκδοχές που εκτοξεύουν:
use autodie qw(open close chdir);
open my $fh, '<', $path; # now dies on failure; no `or die` needed
Το autodie είναι λεξιλογικό: επηρεάζονται μόνο οι κλήσεις στην εμβέλειά του. Στενέψτε την εξαίρεση για συγκεκριμένο σημείο κλήσης:
{
no autodie 'open';
open my $fh, '<', $path or warn "cannot read $path: $!";
}
Προτιμήστε το autodie έναντι του αποσυρμένου αρθρώματος Fatal, το οποίο δεν κάλυπτε συναρτήσεις που επιστρέφουν μετρητές.
Έξοδος χωρίς ενταμιευτή#
Όταν η διαγνωστική έξοδος εξαφανίζεται πριν από κατάρρευση, ή φτάνει παράξενα διαπλεγμένη με μηνύματα warn, η αιτία είναι σχεδόν πάντα stdout με ενταμίευση μπλοκ. Ορίστε το $| στην κορυφή του σεναρίου:
$| = 1;
Κάθε print τώρα εκκενώνει άμεσα. Το κόστος είναι μια μικρή απώλεια απόδοσης I/O· το κέρδος είναι ότι αυτό που βλέπετε στο τερματικό αντιστοιχεί σε αυτό που πραγματικά έκανε το πρόγραμμα, με τη σωστή σειρά.
Για συγκεκριμένο filehandle χωρίς αλλαγή του επιλεγμένου:
use IO::Handle;
$log_fh->autoflush(1);
Συνηθισμένα πρώιμα διαγνωστικά και τι σημαίνουν#
Διαγνωστικό | Σημασία |
|---|---|
| Το strict είναι ενεργό και το |
| Λίστα που ανατέθηκε σε κατακερματισμό έχει περιττό πλήθος· ένα |
| Ένα |
| Μια μεταβλητή πακέτου αναφέρθηκε ακριβώς μία φορά. Σχεδόν πάντα τυπογραφικό ή ένα |
| Ένα |
|
|
Μάθετε περισσότερα#
print-and-die - όταν το preflight δεν αρκεί και χρειάζεστε δομημένα διαγνωστικά χρόνου εκτέλεσης.
exceptions - μετατροπή διαδρομών αποτυχίας σε τυποποιημένες εξαιρέσεις στις οποίες ο καλών μπορεί να ταιριάξει.