調(diào)試

2018-02-24 16:03 更新

開啟?strict?和?warnings

無論何時(shí)調(diào)試代碼,都確信已開啟了?strict?和?warnings?編譯指令。

將下面兩行:

use strict;
use warnings;

放到你試圖調(diào)試或?qū)砜赡芟胝{(diào)試的程序的頂部。

strict?編譯指令強(qiáng)制你使用那些允許 Perl 在編譯時(shí)找出錯(cuò)誤的許多特性。 首先最重要的是,在?strict?下,變量必須在使用前聲明。多數(shù)情況下,這意味 著使用?my

use strict;
my $foo = 7;                # OK, normal variable
print "foo is $fooo\n";     # Perl complains and aborts compilation

沒有?strict,Perl 仍然會(huì)高興地執(zhí)行上面的程序。但你可能會(huì)感到杯具,想不 明白$foo?為何沒有值。啟用?strict?也會(huì)減少許多令人頭痛的輸入錯(cuò)誤。

另外,strict?不允許使用多數(shù)裸字。

no strict;
$foo = Lorem;
print "$foo\n";         # Prints "Lorem"

use strict;
my $foo = ipsum;        # Complains about bareword
$foo = (
    Lorem   => 'ipsum'  # OK, barewords allowed on left of =>
);

$SIG{PIPE} = handler;   # Complains
$SIG{PIPE} = \&handler; # OK
$SIG{PIPE} = "handler"; # Also, OK, but above is preferred

最后,如果你使用符號(hào)引用,啟用?strict?將拋出運(yùn)行時(shí)錯(cuò)誤。

no strict;
$name = "foo";
$$name = "bar";             # Sets the variable $foo to 1
print "$name $$name\n";     # Prints "foo bar"

use strict;
my $name = "foo";
$$name = "bar";             # Complains: can't use "foo" as ref

warnings?編譯指令將使 Perl 吐出許多有用的抱怨,以便讓你知道程序中的 某個(gè)東東并非你所想要的:

use warnings;
my $foo = ;
$foo += 3;
my $foo = 1;            # Compains: redeclaration of variable

my $bar = '12fred34';
my $baz = $bar + 1;     # Complains: Argument "12fred34" isn't numeric
                        # Complains: Name "main::baz" used only once

參閱 strict 及 warnings 的文檔了解其他信息。關(guān)于不用?strict?所帶來的 恐怖故事,可以看看?PerlMonks?上面的帖子。

檢查每個(gè)?open?的返回值

你將經(jīng)常看到人們抱怨下面的代碼無法執(zhí)行:

open( my $file, $filename );
while ( <$file> ) {
    ...
}

接著抱怨?while?循環(huán)也被破壞了。這兒的常見問題是文件?$filename?實(shí)際 上并不存在,因此?open?將失敗。如果沒有檢查,那么你將從來不會(huì)知道。使 用以下代碼替換它:

open( my $file, '<', $filename ) or die "Can't open $filename: $!";

利用?diagnostics?擴(kuò)展警告

有時(shí)候警告消息并沒有解釋你想要的那么多。例如,為何你會(huì)獲得此警告?

Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695.

試試將下列內(nèi)容放到程序頂部并重新執(zhí)行代碼:

use diagnostics;

現(xiàn)在警告看起來像這樣:

Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm
    line 695 (#1)
(W uninitialized) An undefined value was used as if it were already
defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.

To help you figure out what was undefined, perl tells you what operation
you used the undefined value in.  Note, however, that perl optimizes your
program and the operation displayed in the warning may not necessarily
appear literally in your program.  For example, "that $foo" is
usually optimized into "that " . $foo, and the warning will refer to
the concatenation (.) operator, even though there is no . in your
program.

更多的信息將幫助你找出程序的問題。

記住你也可以從命令行指定模塊和編譯指令,因此你甚至不必編輯源代碼來使用diagnostics。使用?-M?命令行選項(xiàng)再次執(zhí)行它:

perl -Mdiagnostics mycode.pl

使用優(yōu)化信號(hào)來獲得棧跟蹤信息

有時(shí)候你將獲得警告,但你并不明白是如何得到的。比如:

Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695.

你可以看到模塊的 695 行代碼干了什么,但你無法看到你的代碼在此時(shí)干了什么。 你將需要看到子例程被調(diào)用的跟蹤信息。

當(dāng) Perl 調(diào)用?die?或?warn?時(shí),它將分別指定?$SIG{__DIE__}?和?$SIG{__WARN__}?來通過子例程。如果你修改它們,讓其成為比?CORE::die?和?CORE::warn?更有用的話,你就得到了一個(gè)有用的調(diào)試工具。這種情況,可以使用?Carp?模塊的?confess?函數(shù)。

在你程序的頂部,添加這些行:

use Carp qw( confess );
$SIG{__DIE__} =  \&confess;
$SIG{__WARN__} = \&confess;

現(xiàn)在,當(dāng)代碼調(diào)用?warn?或?die?時(shí),Carp::confess?函數(shù)將處理它。confess?打印原始警告,跟著棧跟蹤信息,然后停止執(zhí)行程序。

Use of uninitialized value in string eq at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695.
    at /Library/Perl/5.8.6/WWW/Mechanize.pm line 695
        WWW::Mechanize::find_link('WWW::Mechanize=HASH(0x180e5bc)', 'n', 'undef') called at foo.pl line 17
        main::go_find_link('http://www.cnn.com') called at foo.pl line 8

現(xiàn)在我們有更多信息來調(diào)試代碼,包括精確的調(diào)用函數(shù)及傳遞的參數(shù)。從這兒, 我們能夠容易地看到?find_link?的第三個(gè)參數(shù)是?undef,那將是一個(gè)開始 調(diào)查的好地方。

使用 Carp::Always 獲得棧跟蹤信息

如果你不想覆蓋信號(hào)處理器,那么可以安裝 CPAN 模塊?Carp::Always。

在安裝之后,添加下行到你的代碼中:

use Carp::Always;

或者使用?-MCarp::Always?從命令行調(diào)用你的程序,這將總是會(huì)得到棧跟蹤信息。

使用 Devel::REPL 交互執(zhí)行 Perl 代碼

Devel::REPL?模塊提供一個(gè)交互式的 Shell。通過該 Shell,你不用創(chuàng)建 臨時(shí)的源代碼文件就可以做快速的原型開發(fā)及測(cè)試代碼。

在安裝 Devel::REPL 之后,你可以執(zhí)行以下命令啟動(dòng) Shell:

$ re.pl
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)