⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch13.htm

📁 prrl 5 programs codes in the book
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<HTML>

<HEAD>

<TITLE>Chapter 13  -- Handling Errors and Signals</TITLE>



<META>

</HEAD>

<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">

<H1><FONT SIZE=6 COLOR=#FF0000>Chapter&nbsp;13</FONT></H1>

<H1><FONT SIZE=6 COLOR=#FF0000>Handling Errors and Signals</FONT>

</H1>

<HR>

<P>

<CENTER><B><FONT SIZE=5>CONTENTS</FONT></B></CENTER>

<UL>

<LI><A HREF="#CheckingforErrors">

Checking for Errors</A>

<LI><A HREF="#ExampleUsingtheTTFONTSIZEFACECouriererrnoFONTTTFONTSIZEVariableFONT">

Example: Using the <TT>errno</TT>

Variable</FONT></A>

<UL>

<LI><A HREF="#ExampleUsingtheTTFONTSIZEFACECourierorFONTTTFONTSIZELogicalOperatorFONT">

Example: Using the <TT>or</TT>

Logical Operator</FONT></A>

<LI><A HREF="#ExampleUsingtheTTFONTSIZEFACECourierdieFONTTTFONTSIZEFuNCtionFONT">

Example: Using the <TT>die()</TT>

FuNCtion</FONT></A>

<LI><A HREF="#ExampleUsingtheTTFONTSIZEFACECourierwarnFONTTTFONTSIZEFuNCtionFONT">

Example: Using the <TT>warn()</TT>

FuNCtion</FONT></A>

</UL>

<LI><A HREF="#TrappingFatalErrors">

Trapping Fatal Errors</A>

<UL>

<LI><A HREF="#ExampleUsingtheTTFONTSIZEFACECourierevalFONTTTFONTSIZEFuNCtionFONT">

Example: Using the <TT>eval()</TT>

FuNCtion</FONT></A>

</UL>

<LI><A HREF="#WhatIsaSignal">

What Is a Signal?</A>

<UL>

<LI><A HREF="#ExampleHowtoHandleaSignal">

Example: How to Handle a Signal</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>

Most of the examples in this book have been ignoring the fact

that errors can and probably will occur. An error can occur because

the directory you are trying to use does not exist, the disk is

full, or any of a thousand other reasons. Quite often, you won't

be able to do anything to recover from an error, and your program

should exit. However, exiting after displaying a user-friendly

error message is much preferable than waiting until the operating

system or Perl's own error handling takes over.

<P>

After looking at errors generated by fuNCtion calls, we'll look

at a way to prevent certain normally fatal activities-like dividing

by zero-from stopping the execution of your script; this is by

using the <TT>eval()</TT> fuNCtion.

<P>

Then, you'll see what a signal is and how to use the <TT>%SIG</TT>

associative array to create a signal handling fuNCtion.

<H2><A NAME="CheckingforErrors"><FONT SIZE=5 COLOR=#FF0000>

Checking for Errors</FONT></A></H2>

<P>

There is only one way to check for errors in any programming language.

You need to test the return values of the fuNCtions that you call.

Most fuNCtions return zero or false when something goes wrong.

So when using a critical fuNCtion like <TT>open()</TT>

or <TT>sysread()</TT>, checking the

return value helps to ensure that your program will work properly.

<P>

Perl has two special variables-<TT>$?</TT>

and <TT>$!</TT>-that help in finding

out what happened after an error has occurred. The <TT>$?</TT>

variable holds the status of the last pipe close, back-quote string,

or <TT>system()</TT> fuNCtion. The

<TT>$!</TT> variable can be used in

either a numeric or a string context. In a numeric context it

holds the current value of <TT>errno</TT>.

If used in a string context, it holds the error string associated

with <TT>errno</TT>. The variable,

<I>errno</I>, is pre-defined variable that can sometimes be used

to determine the last error that took place. <BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Caution</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

You can't rely on these variables to check the status of pipes, back-quoted strings, or the <TT>system()</TT> fuNCtion when executing scripts under the Windows operating system. My recommendation is to capture the output of the back-quoted string and 
check it directly for error messages. Of course, the command writes its errors to <TT>STDERR</TT> and then can't trap them, and you're out of luck.

</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

ONCe you detect an error and you can't correct the problem without

outside intervention, you need to communicate the problem to the

user. This is usually done with the <TT>die()</TT>

and <TT>warn()</TT> fuNCtions.

<H2><A NAME="ExampleUsingtheTTFONTSIZEFACECouriererrnoFONTTTFONTSIZEVariableFONT"><FONT SIZE=5 COLOR=#FF0000>

Example: Using the <TT>errno</TT>

Variable</FONT></FONT></A></H2>

<P>

When an error occurs, it is common practice for UNIX-based fuNCtions

and programs to set a variable called <TT>errno</TT>

to reflect which error has occurred. If <TT>errno=2</TT>,

then your script tried to access a directory or file that did

not exist. Table 13.1 lists 10 possible values the <TT>errno</TT>

variable can take, but there are hundreds more. If you are interested

in seeing all the possible error values, run the program in Listing

13.1.<BR>

<P>

<CENTER><B>Table 13.1&nbsp;&nbsp;Ten Possible Values for </B><TT><B><FONT FACE="Courier">errno</FONT></B></TT></CENTER>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD WIDTH=59><CENTER><I>Value</I></CENTER></TD><TD WIDTH=356><I>Description</I>

</TD></TR>

<TR><TD WIDTH=59><CENTER>1</CENTER></TD><TD WIDTH=356>Operation not permitted

</TD></TR>

<TR><TD WIDTH=59><CENTER>2</CENTER></TD><TD WIDTH=356>No such file or directory

</TD></TR>

<TR><TD WIDTH=59><CENTER>3</CENTER></TD><TD WIDTH=356>No such process

</TD></TR>

<TR><TD WIDTH=59><CENTER>4</CENTER></TD><TD WIDTH=356>Interrupted fuNCtion call

</TD></TR>

<TR><TD WIDTH=59><CENTER>5</CENTER></TD><TD WIDTH=356>Input/output error

</TD></TR>

<TR><TD WIDTH=59><CENTER>6</CENTER></TD><TD WIDTH=356>No such device or address

</TD></TR>

<TR><TD WIDTH=59><CENTER>7</CENTER></TD><TD WIDTH=356>Arg list too long

</TD></TR>

<TR><TD WIDTH=59><CENTER>8</CENTER></TD><TD WIDTH=356>Exec format error

</TD></TR>

<TR><TD WIDTH=59><CENTER>9</CENTER></TD><TD WIDTH=356>Bad file descriptor

</TD></TR>

<TR><TD WIDTH=59><CENTER>10</CENTER></TD><TD WIDTH=356>No child processes

</TD></TR>

</TABLE>

</CENTER>

<P>

<P>



<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>

<BLOCKQUOTE>

<I>Loop from 1 to 10,000 using </I><TT><I>$!</I></TT><I>

as the loop variable.<BR>

Evaluate the </I><TT><I>$!</I></TT><I>

variable in a string context so that </I><TT><I>$errText</I></TT><I>

is assigned the error message associated with the value of </I><TT><I>$!</I></TT><I>.

<BR>

Use </I><TT><I>chomp()</I></TT><I>

to eliminate possible newlines at the end of an error message.

Some of the messages have newlines, and some don't.<BR>

Print the error message if the message is not </I><TT><I>Unknown

Error</I></TT><I>. Any error value not used by the system

defaults to </I><TT><I>Unknown Error</I></TT><I>.

Using the if statement modifier ensures that only valid error

messages are displayed.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 13.1&nbsp;&nbsp;13LST01.PL-A Program to List All Possible

Values for </B><TT><I><B><FONT FACE="Courier">errno<BR>

</FONT></B></I></TT>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

for ($! = 1; $! &lt;= 10000; $!++) {

    $errText = $!;

    chomp($errText);

    printf(&quot;%04d: %s\n&quot;, $!, $errText) if $! ne &quot;Unknown Error&quot;;

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

Under Windows 95, this program prints 787 error messages. Most

of them are totally unrelated to Perl.

<H3><A NAME="ExampleUsingtheTTFONTSIZEFACECourierorFONTTTFONTSIZELogicalOperatorFONT">

Example: Using the <TT>or</TT>

Logical Operator</FONT></A></H3>

<P>

Perl provides a special logical operator that is ideal for testing

the return values from fuNCtions. You may recall that the <TT>or</TT>

operator will evaluate only the right operand if the left operand

is false. Because most fuNCtions return false when an error occurs,

you can use the <TT>or</TT> operator

to control the display of error messages. For example:

<BLOCKQUOTE>

<PRE>

chdir('/user/printer') or print(&quot;Can't connect to Printer dir.\n&quot;);

</PRE>

</BLOCKQUOTE>

<P>

This code prints only the error message if the program can't change

to the <TT>/user/printer</TT> directory.

Unfortunately, simply telling the user what the problem is, frequently,

is not good enough. The program must also exit to avoid compounding

the problems. You could use the comma operator to add a second

statement to the right operand of the <TT>or</TT>

operator. Adding an <TT>exit()</TT>

statement to the previous line of code looks like this:

<BLOCKQUOTE>

<PRE>

chdir('/usr/printer') or print(&quot;failure\n&quot;), exit(1);

print(&quot;success\n&quot;);

</PRE>

</BLOCKQUOTE>

<P>

I added the extra <TT>print</TT> statement

to prove that the script really exits. If the printer directory

does not exist, the second <TT>print</TT>

statement is not executed.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Note</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

At the shell or DOS, a zero return value means that the program ended successfully. While inside a Perl script, a zero return value frequently means an error has occurred. Be careful when dealing with return values; you should always check your 
documentation. </BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

Using the comma operator to execute two statements instead of

one is awkward and prone to misinterpretation when other programmers

look at the script. Fortunately, you can use the <TT>die()</TT>

fuNCtion to get the same fuNCtionality.

<H3><A NAME="ExampleUsingtheTTFONTSIZEFACECourierdieFONTTTFONTSIZEFuNCtionFONT">

Example: Using the <TT>die()</TT>

FuNCtion</FONT></A></H3>

<P>

The <TT>die()</TT> fuNCtion is used

to quit your script and display a message for the user to read.

Its syntax is

<BLOCKQUOTE>

<PRE>

die(LIST);

</PRE>

</BLOCKQUOTE>

<P>

The elements of <TT>LIST</TT> are

printed to <TT>STDERR</TT>, and then

the script will exit, setting the script's return value to <TT>$!</TT>

(<TT>errno</TT>). If you were running

the Perl script from inside a C program or UNIX script, you could

then check the return value to see what went wrong.

<P>

The simplest way to use the <TT>die()</TT>

fuNCtion is to place it on the right side of the <TT>or</TT>

operator

<BLOCKQUOTE>

<PRE>

chdir('/user/printer') or die();

</PRE>

</BLOCKQUOTE>

<P>

which displays

<BLOCKQUOTE>

<PRE>

Died at test.pl line 2.

</PRE>

</BLOCKQUOTE>

<P>

if the /user/printer directory does not exist. The message is

not too informative, so you should always iNClude a message telling

the user what happened. If you don't know what the error might

be, you can always display the error text associated with errno.

For example:

<BLOCKQUOTE>

<PRE>

chdir('/user/printer') or die(&quot;$!&quot;);

</PRE>

</BLOCKQUOTE>

<P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -