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

📄 ch13.htm

📁 this is a book on pearl , simple example with explanation is given here. it could be beneficial for
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<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 factthat errors can and probably will occur. An error can occur becausethe directory you are trying to use does not exist, the disk isfull, or any of a thousand other reasons. Quite often, you won'tbe able to do anything to recover from an error, and your programshould exit. However, exiting after displaying a user-friendlyerror message is much preferable than waiting until the operatingsystem or Perl's own error handling takes over.<P>After looking at errors generated by fuNCtion calls, we'll lookat a way to prevent certain normally fatal activities-like dividingby zero-from stopping the execution of your script; this is byusing 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 thereturn value helps to ensure that your program will work properly.<P>Perl has two special variables-<TT>$?</TT>and <TT>$!</TT>-that help in findingout 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 ineither a numeric or a string context. In a numeric context itholds the current value of <TT>errno</TT>.If used in a string context, it holds the error string associatedwith <TT>errno</TT>. The variable,<I>errno</I>, is pre-defined variable that can sometimes be usedto 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 withoutoutside intervention, you need to communicate the problem to theuser. 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 fuNCtionsand 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 didnot exist. Table 13.1 lists 10 possible values the <TT>errno</TT>variable can take, but there are hundreds more. If you are interestedin seeing all the possible error values, run the program in Listing13.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" 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>UnknownError</I></TT><I>. Any error value not used by the systemdefaults to </I><TT><I>Unknown Error</I></TT><I>.Using the if statement modifier ensures that only valid errormessages are displayed.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 13.1&nbsp;&nbsp;13LST01.PL-A Program to List All PossibleValues 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. Mostof 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 testingthe return values from fuNCtions. You may recall that the <TT>or</TT>operator will evaluate only the right operand if the left operandis false. Because most fuNCtions return false when an error occurs,you can use the <TT>or</TT> operatorto 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 changeto 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 compoundingthe problems. You could use the comma operator to add a secondstatement 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> statementto prove that the script really exits. If the printer directorydoes 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 ofone is awkward and prone to misinterpretation when other programmerslook 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 usedto 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> areprinted to <TT>STDERR</TT>, and thenthe script will exit, setting the script's return value to <TT>$!</TT>(<TT>errno</TT>). If you were runningthe Perl script from inside a C program or UNIX script, you couldthen 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 isnot too informative, so you should always iNClude a message tellingthe user what happened. If you don't know what the error mightbe, you can always display the error text associated with errno.For example:<BLOCKQUOTE><PRE>chdir('/user/printer') or die(&quot;$!&quot;);</PRE></BLOCKQUOTE><P>This line of code displays<BLOCKQUOTE><PRE>No such file or directory at test.pl line 2.</PRE></BLOCKQUOTE><P>This error message is a bit more informative. It's even betterif you append the text , <TT>stopped</TT>to the error message like this:<BLOCKQUOTE><PRE>chdir('/user/printer') or die(&quot;$!, stopped&quot;);</PRE></BLOCKQUOTE><P>which displays<BLOCKQUOTE><PRE>No such file or directory, stopped at test.pl line 2.</PRE></BLOCKQUOTE><P>Appending the extra string makes the error message look a littlemore professional. If you are really looking for informative errormessages, try this:<BLOCKQUOTE><PRE>$code = &quot;chdir('/user/printer')&quot;;eval($code) or die(&quot;PROBLEM WITH LINE: $code\n$! , stopped&quot;);</PRE></BLOCKQUOTE><P>which displays the following:<BLOCKQUOTE><PRE>PROBLEM WITH LINE: chdir('/user/printer')No such file or directory , stopped at test.pl line 3.</PRE></BLOCKQUOTE><P>The <TT>eval()</TT> fuNCtion is discussedin the section, &quot;Example: Using the <TT>eval()</TT>FuNCtion,&quot; later in this chapter. Therefore, I won't explainwhat this code is doing other than to say that the <TT>eval()</TT>fuNCtion executes its arguments as semi-isolated Perl code. First,the Perl code in <TT>$code</TT> isexecuted and then, if an error arises, the Perl code in <TT>$code</TT>is displayed as text by the <TT>die()</TT>fuNCtion.<P>If you don't want <TT>die()</TT> toadd the script name and line number to the error, add a newlineto the end of the error message. For example:<BLOCKQUOTE><PRE>chdir('/user/printer') or die(&quot;$!\n&quot;);</PRE></BLOCKQUOTE><P>displays the following<BLOCKQUOTE><PRE>No such file or directory</PRE></BLOCKQUOTE><H3><A NAME="ExampleUsingtheTTFONTSIZEFACECourierwarnFONTTTFONTSIZEFuNCtionFONT">Example: Using the <TT>warn()</TT>FuNCtion</FONT></A></H3><P>The <TT>warn()</TT> fuNCtion has thesame fuNCtionality that <TT>die()</TT>does except the script is not exited. This fuNCtion is bettersuited for nonfatal messages like low memory or disk space conditions.The next example tries to change to the <TT>/text</TT>directory. If the connect fails, the consequeNCes are not fatalbecause the files can still be written to the current directory.<BLOCKQUOTE><PRE>chdir('/text') or warn(&quot;Using current directory instead of /text, </FONT><FONT SIZE=2 FACE="ZapfDingbats">&Acirc;</FONT><FONT SIZE=2 FACE="Courier">warning&quot;);</PRE></BLOCKQUOTE><P>This line of code displays<BLOCKQUOTE><PRE>Using current directory instead of /text, warning at test.pl line 2.</PRE></BLOCKQUOTE><P>if the <TT>/text</TT> directory doesnot exist. As with <TT>die()</TT>,you can eliminate the script name and line number by ending yourerror message with a newline. You could also use the <TT>$!</TT>variable to display the system error message.<H2><A NAME="TrappingFatalErrors"><FONT SIZE=5 COLOR=#FF0000>Trapping Fatal Errors</FONT></A></H2><P>There are times when reporting fatal errors and then exiting thescript are not appropriate responses to a problem. For example,your script might try to use the <TT>alarm()</TT>fuNCtion, which is not supported in some versions of Perl. Normally,using an unsupported fuNCtion causes your problem to exit, butyou can use the <TT>eval()</TT> fuNCtionto trap the error and avoid ending the script.<P>The <TT>eval()</TT> fuNCtion acceptsan expression and then executes it. Any errors generated by theexecution will be isolated and not affect the main program. However,all fuNCtion definitions and variable modifications do affectthe main program.<H3><A NAME="ExampleUsingtheTTFONTSIZEFACECourierevalFONTTTFONTSIZEFuNCtionFONT">Example: Using the <TT>eval()</TT>FuNCtion</FONT></A></H3><P>You can use the <TT>eval()</TT> fuNCtionto trap a normally fatal error:<BLOCKQUOTE><PRE>eval { alarm(15) };warn() if $@;eval { print(&quot;The print fuNCtion worked.\n&quot;); };warn() if $@;</PRE></BLOCKQUOTE><P>This program displays the following:<BLOCKQUOTE><PRE>The Unsupported fuNCtion alarm fuNCtion is unimplemented at test.pl line &nbsp;2.        ...caught at test.pl line 3.The print fuNCtion worked.</PRE></BLOCKQUOTE><P>The <TT>$@</TT> special variable holdsthe error message, if any, returned by the execution of the expressionpassed to the <TT>eval()</TT> fuNCtion.If the expression is evaluated correctly, then <TT>$@</TT>is an empty string. You probably remember that an empty stringis evaluated as false when used as a conditional expression.

⌨️ 快捷键说明

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