📄 ch16.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 16 -- Debugging Perl</TITLE>
<META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT SIZE=6 COLOR=#FF0000>Chapter 16</FONT></H1>
<H1><FONT SIZE=6 COLOR=#FF0000>Debugging Perl</FONT></H1>
<HR>
<P>
<CENTER><B><FONT SIZE=5>CONTENTS</FONT></B></CENTER>
<UL>
<LI><A HREF="#SyntaxErrors">
Syntax Errors</A>
<LI><A HREF="#CommonSyntaxErrors">
Common Syntax Errors</A>
<LI><A HREF="#LogicErrors">
Logic Errors</A>
<UL>
<LI><A HREF="#UsingtheTTFONTSIZEFACECourierwFONTTTFONTSIZECommandLineOptionFONT">
Using the <TT>-w</TT>
Command-Line Option</FONT></A>
<LI><A HREF="#BeingStrictwithYourVariables">
Being Strict with Your Variables</A>
<LI><A HREF="#SteppingThroughYourScript">
Stepping Through Your Script</A>
<LI><A HREF="#ExamplesDisplayingInformation">
Examples: Displaying Information</A>
<LI><A HREF="#ExamplesUsingtheFONTSIZEFACELBIHelveticaBlackObliquenFONTFONTSIZECommandFONT">
Examples: Using the n
Command</A>
<LI><A HREF="#ExamplesUsingBreakpoints">
Examples: Using Breakpoints</A>
<LI><A HREF="#ExamplesCreatingCommandAliases">
Examples: Creating Command Aliases</A>
<LI><A HREF="#ExamplesUsingtheDebuggerasanInteractiveInterpreter">
Examples: Using the Debugger as an Interactive Interpreter
</A>
</UL>
<LI><A HREF="#Summary">
Summary</A>
<LI><A HREF="#ReviewQuestions">
Review Questions</A>
<LI><A HREF="#ReviewExercises">
Review Exercises</A>
</UL>
<HR>
<P>
This chapter is about errors: how to find them and how to fix
them. No programmer I've ever known of is able to consistently
create perfect programs. So don't feel bad if you also have some
problems you need to solve. I've spent many hours looking for
a missing closing bracket or a misspelled variable name.
<P>
There are two different types of errors: syntax errors and logic
errors. <I>Syntax</I> errors are made as you type your script
into an editor. For example, you might not add a closing quote
or might misspell a filename. <I>Logic</I> errors are more insidious
and difficult to find. For example, you might place an assignment
statement inside an <TT>if</TT> statement
block that belongs outside the block. Or you might have a loop
that runs from 0 to 100 when it should run from 10 to 100. Accidentally
deleting the 1 or not entering it in the first place is very easy.
<P>
Syntax errors are usually easy to fix. The section "Common
Syntax Errors" discusses some common syntax errors. You'll
see how to decipher some of Perl's error messages.
<P>
Logic errors can be very hard to fix. They are discussed in the
section "Logic Errors." While there is no magic wand
to wave over a program that will identify logic errors, there
are some tools that can help-like the debugger. A <I>debugger</I>
is an environment that lets you execute your program line by line.
This is also called <I>single-stepping</I> through your program.
You can also display or modify the value of variables. The debugger
is discussed in the section "Stepping Through Your Script."
<H2><A NAME="SyntaxErrors"><FONT SIZE=5 COLOR=#FF0000>
Syntax Errors</FONT></A></H2>
<P>
Perl is generally considered an interpreted language. However,
this is not truly accurate. Before being executed, your script
is compiled into an internal format-just like Java's byte-codes
or Pascal's p-code. While Perl is compiling your program, it also
checks for syntax errors. This is why syntax errors are also called
<I>compile-time</I> errors.
<P>
Fixing syntax errors is a matter of reading the error message
displayed by the compiler and then trying to understand which
line of code generated the message and why. The next section,
"Common Syntax Errors," might help. If you are uNCertain
which line of code really generated the error, try commenting
out the likely culprits. Then, re-execute your program and look
at the error messages that are produced to see if they have changed.
<H2><A NAME="CommonSyntaxErrors"><FONT SIZE=5 COLOR=#FF0000>
Common Syntax Errors</FONT></A></H2>
<P>
One very common error is to use <TT>elseif</TT>
instead of the correct <TT>elsif</TT>
keyword. As you program, you'll find that you consistently make
certain kinds of errors. This is okay. Everyone has his or her
own little quirks. Mine is that I keep using the assignment operator
instead of the equality operator. Just remember what your particular
blind spot is. When errors occur, check for your personal common
errors first.
<P>
This section shows some common syntax errors and the error messages
that are generated as a result. First, the error message are shown
and then the script that generated it. After the script, I'll
cast some light as to why that particular message was generated.
<BLOCKQUOTE>
<PRE>
Scalar found where operator expected at test.pl line 2, near "$bar"
(Missing semicolon on previous line?)
$foo = { } # this line is missing a semi-colon.
$bar = 5;
</PRE>
</BLOCKQUOTE>
<P>
Perl sees the anonymous hash on the first line and is expecting
either an operator or the semicolon to follow it. The scalar variable
that it finds, <TT>$bar</TT>, does
not fit the syntax of an expression because two variables can't
be right after each other. In this case, even though the error
message indicates line 2, the problem is in line 1.
<BLOCKQUOTE>
<PRE>
Bare word found where operator expected at
test.pl line 2, near "print("This"
(Might be a runaway multi-line "" string starting on line 1)
syntax error at test.pl line 2, near "print("This is "
String found where operator expected at test.pl line 3, near
"print(""
(Might be a runaway multi-line "" string starting on line 2)
(Missing semicolon on previous line?)
Bare word found where operator expected at
test.pl line 3, near "print("This"
String found where operator expected at test.pl line 3, at end of
line
(Missing operator before ");
?)
Can't find string terminator '"' anywhere before EOF at test.pl
line 3.
print("This is a test.\n); # this line is missing a ending
quote.
print("This is a test.\n");
print("This is a test.\n");
</PRE>
</BLOCKQUOTE>
<P>
In this example, a missing end quote has generated 12 lines of
error messages! You really need to look only at the last one in
order to find out that the problem is a missing string terminator.
While the last error message describes the problem, it does not
tell you where the problem is. For that piece of information,
you need to look at the first line where it tells you to look
at line two. Of course, by this time you already know that if
the error message says line 2, the error is probably in line 1.
<BLOCKQUOTE>
<PRE>
Can't call method "a" in empty package "test" at test.pl line 1.
print(This is a test.\n); # this line is missing a beginning quote.
</PRE>
</BLOCKQUOTE>
<P>
The error being generated here is very cryptic and has little
to do with the actual problem. In order to understand why the
message mentions methods and packages, you need to understand
the different, arcane ways you can invoke methods when programming
with objects. You probably need to add a beginning quote if you
ever see this error message.<BR>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Tip</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
As long as you follow the object calling guidelines used in <A HREF="ch14.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch14.htm" >Chapter 14</A>, "What Are Objects?," you will never have to worry about the more advaNCed ways to call object methods.</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
This list of syntax errors could go on for quite a while, but
you probably understand the basic coNCepts:
<BLOCKQUOTE>
Errors are not always located on the line mentioned in the error
message.<BR>
Errors frequently have nothing to do with the error message displayed.
</BLOCKQUOTE>
<H2><A NAME="LogicErrors"><FONT SIZE=5 COLOR=#FF0000>
Logic Errors</FONT></A></H2>
<P>
These are the programming problems-sometimes called bugs-that
you can stare at for hours without having a clue about why your
script doesn't work. If you find yourself in this position, take
a walk or eat some chocolate. In other words, take a break from
staring at the computer screen. You can also find another programmer
to walk through the code with you. Quite often while explaining
the code to someone else, the problem becomes obvious.
<P>
Besides these two options, you can do the following:
<BLOCKQUOTE>
<B>Use the </B><TT><B><FONT FACE="Courier">-w</FONT></B></TT><B>
Command-line Option</B>-This option will produce warning messages
about questionable code.
</BLOCKQUOTE>
<BLOCKQUOTE>
<B>Use the </B><TT><B><FONT FACE="Courier">strict</FONT></B></TT><B>
pragma</B>-This pragma will force you to declare all variables
before using them.
</BLOCKQUOTE>
<BLOCKQUOTE>
<B>Use the built-in debugger</B>-The built-in debugger will let
you single-step through your script, examining or changing variable
values as needed.
</BLOCKQUOTE>
<P>
Each of these options is discussed in separate sections later.
<P>
As a general rule, when debugging logic errors it helps to break
complex expressions and statements into simpler ones: the simpler,
the better. Use temporary variables if you need to. If you use
the <TT>++</TT> or <TT>-</TT>
operators inside fuNCtion calls or complex expressions, don't.
Move the decrement or iNCrement operation to a separate line.
After the program is debugged, you can always recombine the simple
statements into complex ones.<BR>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Tip</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
One of the most common logic problem is using the assignment operator (<TT>=</TT>) when you should use the equality operator (<TT>==</TT>). If you are creating a conditional expression, you'll almost always use the equality operator (<TT>==</TT>).
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<H3><A NAME="UsingtheTTFONTSIZEFACECourierwFONTTTFONTSIZECommandLineOptionFONT">
Using the <TT>-w</TT>
Command-Line Option</FONT></A></H3>
<P>
One of the most important features to combat logic errors is the
<TT>­w</TT> command-line option,
which causes warning messages to be displayed indicating questionable
Perl code. Questionable code iNCludes identifiers that are mentioned
only oNCe, scalar variables that are used before being set, redefined
subroutines, refereNCes to undefined filehandles, and filehandles
opened read-only that you are attempting to write on.
<P>
For example, can you find anything wrong with the following lines
of code?
<BLOCKQUOTE>
<PRE>
$foo = { };
$bar = 5;
print("$foa\n");
print("$bar\n");
</PRE>
</BLOCKQUOTE>
<P>
You probably can't see anything wrong at first glaNCe. In fact,
this program compiles and runs without complaint. However, running
this program with the <TT>­w</TT>
option (<TT>perl ­w test.pl</TT>)
results in these error messages:
<BLOCKQUOTE>
<PRE>
Identifier "main::foa" used only oNCe: possible typo at test.pl line 4.
Identifier "main::foo" used only oNCe: possible typo at test.pl line 1.
Use of uninitialized value at test.pl line 4.
</PRE>
</BLOCKQUOTE>
<P>
With these error messages, the problem becomes obvious. Either
the variable name <TT>$foo</TT> is
misspelled in the assignment statement or the variable name <TT>$foa</TT>
was misspelled in the print statement.<BR>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Tip</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Always use the <TT>-w</TT> command-line option! Let me repeat this: Always use the <TT>-w</TT> command-line option! Okay? It will save you lots of headaches tracking down bugs that Perl can catch automatically.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
The <TT>-w</TT> option is so useful
that you should <I>always</I> use it. If you know that a specific
line of code is going to generate an error message and you want
to ignore it, use the <TT>$^W</TT>
special variable. For example,
<BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -