| 導購 | 订阅 | 在线投稿
分享
 
 
 

功能豐富的Perl:輕松調試Perl的技巧

2008-05-19 06:25:57  編輯來源:互聯網  简体版  手機版  移動版  評論  字體: ||
 

錯誤所帶來的麻煩

軟件開發人員通常都低估了軟件測試的重要性。這一現象的根本原因很簡單:處理錯誤很困難!因爲錯誤往往暴露了代碼的根本缺陷,所以有時候開發人員甚至會爲了幾個錯誤而從頭開始重新編寫項目的主要部分。

我認爲,調試如此重要,以至于至少要爲其分配整個項目 30% 的時間。額外的調試時間將導致更好的産品。另一方面,如果爲了更快地推出軟件而縮短調試時間,那麽在軟件生成後,您將花上雙份的時間來修複那些稍後暴露出的問題。

有三種基本類型的錯誤:編碼錯誤、文檔錯誤和需求錯誤。需求錯誤通常由于需求不嚴密或缺少需求而導致。文檔錯誤存在于手冊或聯機幫助中。編碼錯誤是由程序員在實現需求時的錯誤而引起的。不幸的是,需求錯誤和文檔錯誤不在本文範圍之內,因此,我們只好只討論如何「檢測」、「解決」和 「修複」編碼錯誤了。

調試的基本概念

我們已經將編碼錯誤定義成程序員在實現需求時産生的錯誤。編碼錯誤會導致不正確的程序行爲(偏離需求的行爲)。因此,程序員在編寫或調試程序之前首先應該知道的是程序需求。

調試與狩獵沒什麽不同。第一步是檢測錯誤(通過觀察錯誤的行爲並確認其模式)。在這個階段,錯誤只是一些症狀。

第二步是解決錯誤。因爲必須要在源代碼中消除錯誤,所以,應該有一個精通程序的人來檢查錯誤,並知道這些錯誤的根本原因。如果代碼理解起來更容易,並且現在的代碼沒有比當初錯誤版本中的代碼更多,則您可能做對了。

第三步,也是最後一步,是修複錯誤(請注意「修複」與「解決」是有區別的)。調試程序將源代碼更改放入「現場」的生産過程,然後檢查它是否正確。如果代碼不正確,則表明您沒有解決錯誤,甚至更糟糕的是,可能還引入了新的錯誤。既然解決錯誤的目的不應該是引入新錯誤,請確保在解決錯誤之後修複每個錯誤。

要確保迅速找到錯誤並很好地理解它們,您應該對調試過程中程序使用模塊和類在每個主要分支處的操作非常清楚。當然,這要求您對編寫代碼所用的語言(在我們的示例中是 Perl)有深入的了解。因爲存在所有這些需求,所以很難找到好的軟件測試人員。

Perl 調試器

Perl 程序員的第一個資源是 Perl 所帶的調試器。如您所見,著手使用該調試器是非常容易的。

用調試器運行一個腳本

perl -d program.pl

Perl 調試器自帶幫助('h' 或 'h h' 分別用于詳細和簡短的幫助屏幕)。perldoc perldebug 頁面(在命令提示窗口輸入 "perldoc perldebug")有更完整的 Perl 調試器描述。

現在,讓我們從一個有錯誤的程序著手,看一下 Perl 調試器是如何工作的。首先,它將嘗試打印一個文件的前 20 行。

buggy.pl

#!/usr/bin/perl -w

use strict;

foreach (0..20)

{

my $line = ;

print "$_ : $line";

}

當它獨自運行時,buggy.pl 將失敗,並給出消息:"Use of uninitialized value in concatenation (.) at ./buggy.pl line 8, line 9."。更神秘的是,它還自己在一行上打印 "9:" 並等待用戶輸入。

那意味著什麽?如果調用了 Perl 調試器,您可能已經找到問題所在了。

首先,讓我們證實這個錯誤是可以重複的。我們將在第 8 行設置一個操作來打印發生錯誤的 $line,然後再運行程序。

buggy.pl 調試器命令

perl -d ./buggy.pl buggy.pl

Default die handler restored.

Loading DB routines from perl5db.pl version 1.07

Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(./buggy.pl:5):

foreach (0..20)

main::(./buggy.pl:6):

{

DB use Data::Dumper

DB a 8 print 'The line variable is now ', Dumper $line

裝入了 Data::Dumper 模塊,以便自動操作可以使用一種美觀的輸出格式。自動操作被設置成每次到達第 8 行時都執行打印語句。現在,讓我們演示一下。

buggy.pl 調試器命令,第 2 部分

DB c

The line variable is now $VAR1 = '#!/usr/bin/perl -w

';

0 : #!/usr/bin/perl -w

The line variable is now $VAR1 = '

';

1 :

The line variable is now $VAR1 = 'use strict;

';

2 : use strict;

The line variable is now $VAR1 = '

';

3 :

The line variable is now $VAR1 = 'foreach (0..20)

';

4 : foreach (0..20)

The line variable is now $VAR1 = '{

';

5 : {

The line variable is now $VAR1 = ' my $line = ;

';

6 :

my $line = ;

The line variable is now $VAR1 = ' print "$_ : $line";

';

7 :

print "$_ : $line";

The line variable is now $VAR1 = '}

';

8 : }

The line variable is now $VAR1 = undef;

Use of uninitialized value in concatenation (.) at ./buggy.pl line 8, line 9.

9 :

現在很清楚,沒有定義行變量時就會出問題。而且,程序等待更多的輸入。再按 11 次回車鍵産生了以下輸出:

buggy.pl 調試器命令,第 3 部分

The line variable is now $VAR1 = '

';

10 :

The line variable is now $VAR1 = '

';

11 :

The line variable is now $VAR1 = '

';

12 :

The line variable is now $VAR1 = '

';

13 :

The line variable is now $VAR1 = '

';

14 :

The line variable is now $VAR1 = '

';

15 :

The line variable is now $VAR1 = '

';

16 :

The line variable is now $VAR1 = '

';

17 :

The line variable is now $VAR1 = '

';

18 :

The line variable is now $VAR1 = '

';

19 :

The line variable is now $VAR1 = '

';

20 :

Debugged program terminated.

Use q to quit or R to restart,

use O inhibit_exit to avoid stopping after program termination,

h q, h R or h O to get additional info.

DB

到現在爲止已經很清楚了,由于即使在不存在行的情況下,程序仍無條件地等待 20 行的輸入,所以程序會出錯。修複就是要在從 filehandle 讀取 $line 之後測試它:

buggy.pl fixed

#!/usr/bin/perl -w

use strict;

foreach (0..20)

{

my $line = ;

last unless defined $line;# exit loop if $line is not defined

print "$_ : $line";

}

如您所見,修複過的程序在所有情況下都可以正確工作!

關于 Perl 調試器的結論

Emacs 編輯器支持 Perl 調試器並使其更易于使用。您可以在 Emacs 中使用 Info(輸入 M-x info)來閱讀有關 GUD Emacs 的更詳細信息。GUD 是與 Perl 調試器一起工作的全局調試方式(當在 Emacs 中編輯 Perl 程序時輸入 M-x perldb)。

只需少量工作就可以讓 vi 系列的編輯器也能支持 Perl 調試器。有關詳細信息,請參閱 perldoc perldebug 頁面。有關其它編輯器的信息,請參考每個編輯器的文檔。

Perl 內置的調試器是一個強大的工具,可以執行比我們剛剛看到的簡單用法複雜得多的任務。但它的確要求使用者具備大量 Perl 專門知識。正因爲如此,我們現在要看一些簡單些的工具,這些工具將更適合初級和中級 Perl 程序員。

Devel::ptkdb

要使用 Devel::ptkdb 調試器,首先得從 CPAN(請參閱下面的參考資料)下載它並將它安裝在您的系統上。(某些用戶可能還需要安裝 Tk 模塊,該模塊也可以從 CPAN 獲得。)就我個人看來,Devel::ptkdb 在 UNIX 系統(如 Linux)上最好用。(雖然在理論上 Devel::ptkdb 並不限于與 UNIX 兼容的系統,但是,我從未聽說過有人成功地在 Windows 上使用 Devel::ptkdb。正如一句老話所講:除了滑雪穿過旋轉門之外,任何事都是可能的。)

如果無法讓系統管理員爲您安裝(例如,因爲您自己就是系統管理員),可以嘗試在命令提示行執行以下操作(可能需要以 root 身份執行這些操作):

從 CPAN 安裝 Devel::ptkdb

perl -MCPAN -e'install Tk'

perl -MCPAN -e'install Devel::ptkdb'

如果是第一次運行 CPAN 安裝例程,那麽,在回答一些初始問題之後,將自動下載並安裝適當的模塊。

可以用 ptkdb 調試器運行程序,如下所示(使用我們以前的 buggy.pl 示例):

使用 Devel::ptkdb

perl -d:ptkdb buggy.pl buggy.pl

要閱讀 Devel::ptkdb 模塊的文檔,請使用命令 "perldoc Devel::ptkdb"。我們在本文中使用版本 1.1071。(雖然更新的版本可能隨時問世,但它們與我們正在使用的版本應該沒有很大的不

 
  錯誤所帶來的麻煩   軟件開發人員通常都低估了軟件測試的重要性。這一現象的根本原因很簡單:處理錯誤很困難!因爲錯誤往往暴露了代碼的根本缺陷,所以有時候開發人員甚至會爲了幾個錯誤而從頭開始重新編寫項目的主要部分。   我認爲,調試如此重要,以至于至少要爲其分配整個項目 30% 的時間。額外的調試時間將導致更好的産品。另一方面,如果爲了更快地推出軟件而縮短調試時間,那麽在軟件生成後,您將花上雙份的時間來修複那些稍後暴露出的問題。   有三種基本類型的錯誤:編碼錯誤、文檔錯誤和需求錯誤。需求錯誤通常由于需求不嚴密或缺少需求而導致。文檔錯誤存在于手冊或聯機幫助中。編碼錯誤是由程序員在實現需求時的錯誤而引起的。不幸的是,需求錯誤和文檔錯誤不在本文範圍之內,因此,我們只好只討論如何「檢測」、「解決」和 「修複」編碼錯誤了。   調試的基本概念   我們已經將編碼錯誤定義成程序員在實現需求時産生的錯誤。編碼錯誤會導致不正確的程序行爲(偏離需求的行爲)。因此,程序員在編寫或調試程序之前首先應該知道的是程序需求。   調試與狩獵沒什麽不同。第一步是檢測錯誤(通過觀察錯誤的行爲並確認其模式)。在這個階段,錯誤只是一些症狀。   第二步是解決錯誤。因爲必須要在源代碼中消除錯誤,所以,應該有一個精通程序的人來檢查錯誤,並知道這些錯誤的根本原因。如果代碼理解起來更容易,並且現在的代碼沒有比當初錯誤版本中的代碼更多,則您可能做對了。   第三步,也是最後一步,是修複錯誤(請注意「修複」與「解決」是有區別的)。調試程序將源代碼更改放入「現場」的生産過程,然後檢查它是否正確。如果代碼不正確,則表明您沒有解決錯誤,甚至更糟糕的是,可能還引入了新的錯誤。既然解決錯誤的目的不應該是引入新錯誤,請確保在解決錯誤之後修複每個錯誤。   要確保迅速找到錯誤並很好地理解它們,您應該對調試過程中程序使用模塊和類在每個主要分支處的操作非常清楚。當然,這要求您對編寫代碼所用的語言(在我們的示例中是 Perl)有深入的了解。因爲存在所有這些需求,所以很難找到好的軟件測試人員。   Perl 調試器   Perl 程序員的第一個資源是 Perl 所帶的調試器。如您所見,著手使用該調試器是非常容易的。   用調試器運行一個腳本   perl -d program.pl   Perl 調試器自帶幫助('h' 或 'h h' 分別用于詳細和簡短的幫助屏幕)。perldoc perldebug 頁面(在命令提示窗口輸入 "perldoc perldebug")有更完整的 Perl 調試器描述。   現在,讓我們從一個有錯誤的程序著手,看一下 Perl 調試器是如何工作的。首先,它將嘗試打印一個文件的前 20 行。   buggy.pl   #!/usr/bin/perl -w   use strict;   foreach (0..20)   {   my $line = ;   print "$_ : $line";   }   當它獨自運行時,buggy.pl 將失敗,並給出消息:"Use of uninitialized value in concatenation (.) at ./buggy.pl line 8, line 9."。更神秘的是,它還自己在一行上打印 "9:" 並等待用戶輸入。   那意味著什麽?如果調用了 Perl 調試器,您可能已經找到問題所在了。   首先,讓我們證實這個錯誤是可以重複的。我們將在第 8 行設置一個操作來打印發生錯誤的 $line,然後再運行程序。   buggy.pl 調試器命令    perl -d ./buggy.pl buggy.pl   Default die handler restored.   Loading DB routines from perl5db.pl version 1.07   Editor support available.   Enter h or `h h' for help, or `man perldebug' for more help.   main::(./buggy.pl:5):   foreach (0..20)   main::(./buggy.pl:6):   {   DB use Data::Dumper   DB a 8 print 'The line variable is now ', Dumper $line   裝入了 Data::Dumper 模塊,以便自動操作可以使用一種美觀的輸出格式。自動操作被設置成每次到達第 8 行時都執行打印語句。現在,讓我們演示一下。   buggy.pl 調試器命令,第 2 部分   DB c   The line variable is now $VAR1 = '#!/usr/bin/perl -w   ';   0 : #!/usr/bin/perl -w   The line variable is now $VAR1 = '   ';   1 :   The line variable is now $VAR1 = 'use strict;   ';   2 : use strict;   The line variable is now $VAR1 = '   ';   3 :   The line variable is now $VAR1 = 'foreach (0..20)   ';   4 : foreach (0..20)   The line variable is now $VAR1 = '{   ';   5 : {   The line variable is now $VAR1 = ' my $line = ;   ';   6 :   my $line = ;   The line variable is now $VAR1 = ' print "$_ : $line";   ';   7 :   print "$_ : $line";   The line variable is now $VAR1 = '}   ';   8 : }   The line variable is now $VAR1 = undef;   Use of uninitialized value in concatenation (.) at ./buggy.pl line 8, line 9.   9 :   現在很清楚,沒有定義行變量時就會出問題。而且,程序等待更多的輸入。再按 11 次回車鍵産生了以下輸出:   buggy.pl 調試器命令,第 3 部分   The line variable is now $VAR1 = '   ';   10 :   The line variable is now $VAR1 = '   ';   11 :   The line variable is now $VAR1 = '   ';   12 :   The line variable is now $VAR1 = '   ';   13 :   The line variable is now $VAR1 = '   ';   14 :   The line variable is now $VAR1 = '   ';   15 :   The line variable is now $VAR1 = '   ';   16 :   The line variable is now $VAR1 = '   ';   17 :   The line variable is now $VAR1 = '   ';   18 :   The line variable is now $VAR1 = '   ';   19 :   The line variable is now $VAR1 = '   ';   20 :   Debugged program terminated.   Use q to quit or R to restart,   use O inhibit_exit to avoid stopping after program termination,   h q, h R or h O to get additional info.   DB   到現在爲止已經很清楚了,由于即使在不存在行的情況下,程序仍無條件地等待 20 行的輸入,所以程序會出錯。修複就是要在從 filehandle 讀取 $line 之後測試它:   buggy.pl fixed   #!/usr/bin/perl -w   use strict;   foreach (0..20)   {   my $line = ;   last unless defined $line; # exit loop if $line is not defined   print "$_ : $line";   }   如您所見,修複過的程序在所有情況下都可以正確工作!   關于 Perl 調試器的結論   Emacs 編輯器支持 Perl 調試器並使其更易于使用。您可以在 Emacs 中使用 Info(輸入 M-x info)來閱讀有關 GUD Emacs 的更詳細信息。GUD 是與 Perl 調試器一起工作的全局調試方式(當在 Emacs 中編輯 Perl 程序時輸入 M-x perldb)。   只需少量工作就可以讓 vi 系列的編輯器也能支持 Perl 調試器。有關詳細信息,請參閱 perldoc perldebug 頁面。有關其它編輯器的信息,請參考每個編輯器的文檔。   Perl 內置的調試器是一個強大的工具,可以執行比我們剛剛看到的簡單用法複雜得多的任務。但它的確要求使用者具備大量 Perl 專門知識。正因爲如此,我們現在要看一些簡單些的工具,這些工具將更適合初級和中級 Perl 程序員。   Devel::ptkdb   要使用 Devel::ptkdb 調試器,首先得從 CPAN(請參閱下面的參考資料)下載它並將它安裝在您的系統上。(某些用戶可能還需要安裝 Tk 模塊,該模塊也可以從 CPAN 獲得。)就我個人看來,Devel::ptkdb 在 UNIX 系統(如 Linux)上最好用。(雖然在理論上 Devel::ptkdb 並不限于與 UNIX 兼容的系統,但是,我從未聽說過有人成功地在 Windows 上使用 Devel::ptkdb。正如一句老話所講:除了滑雪穿過旋轉門之外,任何事都是可能的。)   如果無法讓系統管理員爲您安裝(例如,因爲您自己就是系統管理員),可以嘗試在命令提示行執行以下操作(可能需要以 root 身份執行這些操作):   從 CPAN 安裝 Devel::ptkdb   perl -MCPAN -e'install Tk'   perl -MCPAN -e'install Devel::ptkdb'   如果是第一次運行 CPAN 安裝例程,那麽,在回答一些初始問題之後,將自動下載並安裝適當的模塊。   可以用 ptkdb 調試器運行程序,如下所示(使用我們以前的 buggy.pl 示例):   使用 Devel::ptkdb   perl -d:ptkdb buggy.pl buggy.pl   要閱讀 Devel::ptkdb 模塊的文檔,請使用命令 "perldoc Devel::ptkdb"。我們在本文中使用版本 1.1071。(雖然更新的版本可能隨時問世,但它們與我們正在使用的版本應該沒有很大的不   
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
王朝網路微信公眾號
微信掃碼關註本站公眾號 wangchaonetcn
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有