Home arrow Perl Programming arrow Page 2 - Using The Perl Debugger

Step By Step - Perl

One of Perl's better-kept secrets is its built-in debugger, a powerful utility that allows developers to rapidly track down errors in their Perl scripts. This article introduces you to the Perl debugger, explaining how to use it to step through scripts, set breakpoints, inspect variables and objects, watch expressions and perform stack traces.

TABLE OF CONTENTS:
  1. Using The Perl Debugger
  2. Step By Step
  3. Breaking Free
  4. A Watchful Eye
  5. Acts Of Madness
  6. Test Drive
By: icarus, (c) Melonfire
Rating: starstarstarstarstar / 39
June 25, 2003

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

When you first enter the debugger, you're placed at the first executable line of your Perl script.


$ perl -d mailer.pl 877
Loading DB routines from perl5db.pl version 1.19
Editor support available.

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

main::(mailer.pl:6): unless($ARGV[0])
main::(mailer.pl:7): {
DB<1>

It's important to note that this line has not yet been executed; rather, it is the line that will be executed next. This is a very common mistake made by newbies to the Perl debugger, so be warned!

In order to execute the next line of the script, type "s".


main::(mailer.pl:6): unless($ARGV[0])
main::(mailer.pl:7): {
DB<1> s
main::(mailer.pl:12): my $id = $ARGV[0];
DB<1> s
main::(mailer.pl:16): my $dbh =
DBI->connect("DBI:mysql:database=db198;host=localhost", "root",
DBI->"secret",
{'RaiseError' => 1}) or die ("Cannot connect to database");
DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm
:442):
442: my $class = shift;
DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm
:443):
443: my($dsn, $user, $pass, $attr, $old_driver) = @_;
DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm
:444):
444: my $driver;
DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm
:445):
445: my $dbh;
DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm
:448):
448: ($old_driver, $attr) = ($attr, $old_driver) if $attr and
!ref($attr);
DB<1> s

The "s" command steps through each line of the script, ducking into subroutines as and when needed - as clearly illustrated in the snippet above (note how the status message next to each line of the script changes to display which subroutine the script is currently executing).

If you'd like to "step over" subroutines, you can use the "n" command instead, which executes subroutines as a single step. This is useful if you have a large number of subroutine calls in your code and are more interested in general program flow than specific or isolated problems.


main::(mailer.pl:6): unless($ARGV[0])
main::(mailer.pl:7): {
DB<1> n
main::(mailer.pl:12): my $id = $ARGV[0];
DB<1> n
main::(mailer.pl:16): my $dbh =
DBI->connect("DBI:mysql:database=test;host=localhost", "root", "",
{'RaiseError' => 1}) or die ("Cannot connect to database");
DB<1> n
nmain::(mailer.pl:19): my $sendmail = "/usr/sbin/sendmail -t";
DB<1>
main::(mailer.pl:20): my $reply_to = "Reply-to: foo\@bar.org";
DB<1> n
main::(mailer.pl:21): my $subject = "Subject: FOOBAR";
DB<1> n
main::(mailer.pl:22): my $content = "Hello and how are you doing?
This is the message body";

You can hit the "Enter" key repeatedly to repeat the last "n" or "s" command.

You can use the "l" command you learnt on the previous page to view the contents of a subroutine, simply by specifying the package/subroutine name after the "l" command.


DB<11> l DBI::connect
Switching to file '/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm'.
441 sub connect {
442: my $class = shift;
443: my($dsn, $user, $pass, $attr, $old_driver) = @_;
444: my $driver;
445: my $dbh;
446
447 # switch $old_driver<->$attr if called in old style
448: ($old_driver, $attr) = ($attr, $old_driver) if $attr and
!ref($attr);
449
450: my $connect_meth = (ref $attr) ? $attr->{dbi_connect_method} :
undef;

If you're currently inside a subroutine and would like to execute all its remaining statements until it generates a return value, simply use the "r" command. The debugger will continue through the subroutine, and print the return value from the subroutine once it finishes execution.


DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm
:443):
443: my($dsn, $user, $pass, $attr, $old_driver) = @_;
DB<1> r
scalar context return from DBI::connect: empty hash
main::(mailer.pl:19): my $sendmail = "/usr/sbin/sendmail -t";

{mospagebreak title=Digging Deeper}

One of the Perl debugger's most oft-used features is its ability to X-ray any variable or object and display its contents. This is accomplised via the "x" command, as illustrated in the following example:


DB<7> @friends = qw(Rachel Ross Joey Monica Chandler Phoebe);

DB<8> x @friends
0 'Rachel'
1 'Ross'
2 'Joey'
3 'Monica'
4 'Chandler'
5 'Phoebe

You can use the "p" command to print the value of any variable,


DB<4> p $sendmail
/usr/sbin/sendmail -t

DB<7> $movie="Star Wars"

DB<8> p $movie
Star Wars

or the "V" command, followed by a package name, to view all the variables in that package.


DB<32> V DBI
%DBI_methods = (
'db' => HASH(0x81e292c)
'CLEAR' => HASH(0x8281ff8)
'O' => 4
'DESTROY' => undef
'EXISTS' => HASH(0x8281ff8)
-> REUSED_ADDRESS
'FETCH' => HASH(0x808b198)
'O' => 1028
'FIRSTKEY' => HASH(0x8281ff8)
-> REUSED_ADDRESS
'NEXTKEY' => HASH(0x8281ff8)
-> REUSED_ADDRESS
'STORE' => HASH(0x8284968)
'O' => 1040
'_not_impl' => undef
'begin_work' => HASH(0x83155a8)
'O' => 1024
'U' => ARRAY(0x831556c)
0 1
1 2
2 '[ \\%attr ]'
'column_info' => HASH(0x81e2680)
'O' => 512
'U' => ARRAY(0x81e2644)
0 1
1 6
2 '$catalog, $schema, $table, $column [, \\%attr ]'
'commit' => HASH(0x8315608)
'O' => 1152
'U' => ARRAY(0x83155d8)
0 1
1 1
...

The "X" command displays a complete list of all the variables the Perl script knows about, including environment and shell variables, special Perl built-ins and variables local to the script itself.


DB<32> X
FileHandle(STDIN) => fileno(0)
$^V = "\cE\cH\c@"
$2 = ''
$1 = 'main'
$movie = 'Star Wars'
$^WARNING_BITS = "\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@"
$< = 515
FileHandle(stdin) => fileno(0)
@ARGV = (
0 'ueruir'
)
@INC = (
0 '/usr/lib/perl5/5.8.0/i386-linux-thread-multi'
1 '/usr/lib/perl5/5.8.0'
2 '/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi'
3 '/usr/lib/perl5/site_perl/5.8.0'
4 '/usr/lib/perl5/site_perl'
5 '/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi'
6 '/usr/lib/perl5/vendor_perl/5.8.0'
7 '/usr/lib/perl5/vendor_perl'
8 '.'
)
%INC = (
'AutoLoader.pm' => '/usr/lib/perl5/5.8.0/AutoLoader.pm'
'Carp.pm' => '/usr/lib/perl5/5.8.0/Carp.pm'
'Carp/Heavy.pm' => '/usr/lib/perl5/5.8.0/Carp/Heavy.pm'
'Config.pm' => '/usr/lib/perl5/5.8.0/i386-linux-thread-multi/Config.pm'
'DBD/mysql.pm' => '/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/DBD/mysql.pm'
...

You can also use the "M" command to display a list of all loaded modules (together with version numbers),


DB<32> M
'AutoLoader.pm' => '5.59 from /usr/lib/perl5/5.8.0/AutoLoader.pm'
'Carp.pm' => '1.01 from /usr/lib/perl5/5.8.0/Carp.pm' 'Carp/Heavy.pm' => '/usr/lib/perl5/5.8.0/Carp/Heavy.pm'
'Config.pm' => '/usr/lib/perl5/5.8.0/i386-linux-thread-multi/Config.pm'
'DBD/mysql.pm' => '2.0416 from /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/DBD/mysql.pm'
'DBI.pm' => '1.30 from /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm'
'DynaLoader.pm' => '1.04 from /usr/lib/perl5/5.8.0/i386-linux-thread-multi/DynaLoader.pm'
'Exporter.pm' => '5.566 from /usr/lib/perl5/5.8.0/Exporter.pm' 'Exporter/Heavy.pm' => '5.566 from /usr/lib/perl5/5.8.0/Exporter/Heavy.pm'
'Term/Cap.pm' => '1.07 from /usr/lib/perl5/5.8.0/Term/Cap.pm' 'Term/ReadLine.pm' => '1.00 from /usr/lib/perl5/5.8.0/Term/ReadLine.pm'
'dumpvar.pl' => '/usr/lib/perl5/5.8.0/dumpvar.pl'
'perl5db.pl' => '1.19 from /usr/lib/perl5/5.8.0/perl5db.pl' 'strict.pm' => '1.02 from /usr/lib/perl5/5.8.0/strict.pm' 'vars.pm' => '1.01 from /usr/lib/perl5/5.8.0/vars.pm' 'warnings.pm' => '1.00 from /usr/lib/perl5/5.8.0/warnings.pm' 'warnings/register.pm' => '1.00 from /usr/lib/perl5/5.8.0/warnings/register.pm'

and the "m" command, followed by a package name, to view the methods available in that package.


DB<33> m DBI
CLONE
_clone_dbis
_dbtype_names
_debug_dispatch
_rebless
_rebless_dbtype_subclass
_set_isa
_setup_driver
available_drivers
bootstrap
carp
confess
connect
connect_cached
connect_test_perf
constant
croak
data_sources
dbi_profile
via Exporter: export_ok_tags
via Exporter: export_tags
via Exporter: export_to_level
via DynaLoader: AUTOLOAD
via DynaLoader: boot_DynaLoader
via DynaLoader: dl_install_xsub
...

Finally, you can obtain a complete list of subroutines in your script (and all its linked packages) with the "S" command,


DB<35> S
AutoLoader::AUTOLOAD
AutoLoader::BEGIN AutoLoader::__ANON__[/usr/lib/perl5/5.8.0/AutoLoader.pm:96]
AutoLoader::import
AutoLoader::unimport
Carp::BEGIN
Carp::caller_info
Carp::carp
Carp::cluck
Carp::confess
Carp::croak
Carp::export_fail
Carp::format_arg
Carp::get_status
DBD::mysql::AUTOLOAD
DBD::mysql::BEGIN
DBD::mysql::_OdbcParse
DBD::mysql::_OdbcParseHost
DBD::mysql::db::ANSI2db
DBD::mysql::db::BEGIN
DBD::mysql::db::_SelectDB
DBD::mysql::db::admin
DBI::BEGIN
DBI::CLONE
DBI::DBI_tie::STORE
...

and filter that list down to a specific subset by adding a search pattern.


DB<35> S connect
DBD::_::db::disconnect
DBD::_::dr::connect
DBD::_::dr::connect_cached
DBD::_::dr::disconnect_all
DBD::mysql::dr::connect
DBI::connect
DBI::connect_cached
DBI::connect_test_perf
DBI::disconnect
DBI::disconnect_all



 
 
>>> More Perl Programming Articles          >>> More By icarus, (c) Melonfire
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PERL PROGRAMMING ARTICLES

- Perl Turns 25
- Lists and Arguments in Perl
- Variables and Arguments in Perl
- Understanding Scope and Packages in Perl
- Arguments and Return Values in Perl
- Invoking Perl Subroutines and Functions
- Subroutines and Functions in Perl
- Perl Basics: Writing and Debugging Programs
- Structure and Statements in Perl
- First Steps in Perl
- Completing Regular Expression Basics
- Modifiers, Boundaries, and Regular Expressio...
- Quantifiers and Other Regular Expression Bas...
- Parsing and Regular Expression Basics
- Hash Functions

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: