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

📄 library_20.html

📁 Linux程序员的工作手册
💻 HTML
字号:
<!-- This HTML file has been created by texi2html 1.27     from library.texinfo on 3 March 1994 --><TITLE>The GNU C Library - Non-Local Exits</TITLE><P>Go to the <A HREF="library_19.html" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_19.html">previous</A>, <A HREF="library_21.html" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html">next</A> section.<P><A NAME="IDX1442"></A><A NAME="IDX1443"></A><H1><A NAME="SEC326" HREF="library_toc.html#SEC326" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC326">Non-Local Exits</A></H1><P>Sometimes when your program detects an unusual situation inside a deeplynested set of function calls, you would like to be able to immediatelyreturn to an outer level of control.  This section describes how you cando such <DFN>non-local exits</DFN> using the <CODE>setjmp</CODE> and <CODE>longjmp</CODE>functions.<P><H2><A NAME="SEC327" HREF="library_toc.html#SEC327" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC327">Introduction to Non-Local Exits</A></H2><P>As an example of a situation where a non-local exit can be useful,suppose you have an interactive program that has a "main loop" thatprompts for and executes commands.  Suppose the "read" command readsinput from a file, doing some lexical analysis and parsing of the inputwhile processing it.  If a low-level input error is detected, it wouldbe useful to be able to return immediately to the "main loop" insteadof having to make each of the lexical analysis, parsing, and processingphases all have to explicitly deal with error situations initiallydetected by nested calls.<P>(On the other hand, if each of these phases has to do a substantialamount of cleanup when it exits--such as closing files, deallocatingbuffers or other data structures, and the like--then it can be moreappropriate to do a normal return and have each phase do its owncleanup, because a non-local exit would bypass the intervening phases andtheir associated cleanup code entirely.  Alternatively, you could use anon-local exit but do the cleanup explicitly either before or afterreturning to the "main loop".)<P>In some ways, a non-local exit is similar to using the <SAMP>`return'</SAMP>statement to return from a function.  But while <SAMP>`return'</SAMP> abandonsonly a single function call, transferring control back to the point atwhich it was called, a non-local exit can potentially abandon manylevels of nested function calls.<P>You identify return points for non-local exits calling the function<CODE>setjmp</CODE>.  This function saves information about the executionenvironment in which the call to <CODE>setjmp</CODE> appears in an object oftype <CODE>jmp_buf</CODE>.  Execution of the program continues normally afterthe call to <CODE>setjmp</CODE>, but if a exit is later made to this returnpoint by calling <CODE>longjmp</CODE> with the corresponding <CODE>jmp_buf</CODE>object, control is transferred back to the point where <CODE>setjmp</CODE> wascalled.  The return value from <CODE>setjmp</CODE> is used to distinguishbetween an ordinary return and a return made by a call to<CODE>longjmp</CODE>, so calls to <CODE>setjmp</CODE> usually appear in an <SAMP>`if'</SAMP>statement.<P>Here is how the example program described above might be set up:  <P><PRE>#include &#60;setjmp.h&#62;#include &#60;stdlib.h&#62;#include &#60;stdio.h&#62;jmp_buf main_loop;void abort_to_main_loop (int status){  longjmp (main_loop, status);}intmain (void){  while (1)    if (setjmp (main_loop))      puts ("Back at main loop....");    else      do_command ();}void do_command (void){  char buffer[128];  if (fgets (buffer, 128, stdin) == NULL)    abort_to_main_loop (-1);  else    exit (EXIT_SUCCESS);}</PRE><P>The function <CODE>abort_to_main_loop</CODE> causes an immediate transfer ofcontrol back to the main loop of the program, no matter where it iscalled from.<P>The flow of control inside the <CODE>main</CODE> function may appear a littlemysterious at first, but it is actually a common idiom with<CODE>setjmp</CODE>.  A normal call to <CODE>setjmp</CODE> returns zero, so the"else" clause of the conditional is executed.  If<CODE>abort_to_main_loop</CODE> is called somewhere within the execution of<CODE>do_command</CODE>, then it actually appears as if the <EM>same</EM> callto <CODE>setjmp</CODE> in <CODE>main</CODE> were returning a second time with a valueof <CODE>-1</CODE>.<P>So, the general pattern for using <CODE>setjmp</CODE> looks something like:<P><PRE>if (setjmp (<VAR>buffer</VAR>))  /* Code to clean up after premature return. */  ...else  /* Code to be executed normally after setting up the return point. */  ...</PRE><P><H2><A NAME="SEC328" HREF="library_toc.html#SEC328" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC328">Details of Non-Local Exits</A></H2><P>Here are the details on the functions and data structures used forperforming non-local exits.  These facilities are declared in<TT>`setjmp.h'</TT>.<A NAME="IDX1444"></A><P><A NAME="IDX1445"></A><U>Data Type:</U> <B>jmp_buf</B><P>Objects of type <CODE>jmp_buf</CODE> hold the state information tobe restored by a non-local exit.  The contents of a <CODE>jmp_buf</CODE>identify a specific place to return to.<P><A NAME="IDX1446"></A><U>Macro:</U> int <B>setjmp</B> <I>(jmp_buf <VAR>state</VAR>)</I><P>When called normally, <CODE>setjmp</CODE> stores information about theexecution state of the program in <VAR>state</VAR> and returns zero.  If<CODE>longjmp</CODE> is later used to perform a non-local exit to this<VAR>state</VAR>, <CODE>setjmp</CODE> returns a nonzero value.<P><A NAME="IDX1447"></A><U>Function:</U> void <B>longjmp</B> <I>(jmp_buf <VAR>state</VAR>, int <VAR>value</VAR>)</I><P>This function restores current execution to the state saved in<VAR>state</VAR>, and continues execution from the call to <CODE>setjmp</CODE> thatestablished that return point.  Returning from <CODE>setjmp</CODE> by means of<CODE>longjmp</CODE> returns the <VAR>value</VAR> argument that was passed to<CODE>longjmp</CODE>, rather than <CODE>0</CODE>.  (But if <VAR>value</VAR> is given as<CODE>0</CODE>, <CODE>setjmp</CODE> returns <CODE>1</CODE>).<P>There are a lot of obscure but important restrictions on the use of<CODE>setjmp</CODE> and <CODE>longjmp</CODE>.  Most of these restrictions arepresent because non-local exits require a fair amount of magic on thepart of the C compiler and can interact with other parts of the languagein strange ways.<P>The <CODE>setjmp</CODE> function is actually a macro without an actualfunction definition, so you shouldn't try to <SAMP>`#undef'</SAMP> it or takeits address.  In addition, calls to <CODE>setjmp</CODE> are safe in only thefollowing contexts:<P><UL><LI>As the test expression of a selection or iterationstatement (such as <SAMP>`if'</SAMP> or <SAMP>`while'</SAMP>).<P><LI>As one operand of a equality or comparison operator that appears as thetest expression of a selection or iteration statement.  The otheroperand must be an integer constant expression.<P><LI>As the operand of a unary <SAMP>`!'</SAMP> operator, that appears as thetest expression of a selection or iteration statement.<P><LI>By itself as an expression statement.</UL><P>Return points are valid only during the dynamic extent of the functionthat called <CODE>setjmp</CODE> to establish them.  If you <CODE>longjmp</CODE> toa return point that was established in a function that has alreadyreturned, unpredictable and disastrous things are likely to happen.<P>You should use a nonzero <VAR>value</VAR> argument to <CODE>longjmp</CODE>.  While<CODE>longjmp</CODE> refuses to pass back a zero argument as the return valuefrom <CODE>setjmp</CODE>, this is intended as a safety net against accidentalmisuse and is not really good programming style.<P>When you perform a non-local exit, accessible objects generally retainwhatever values they had at the time <CODE>longjmp</CODE> was called.  Theexception is that the values of automatic variables local to thefunction containing the <CODE>setjmp</CODE> call that have been changed sincethe call to <CODE>setjmp</CODE> are indeterminate, unless you have declaredthem <CODE>volatile</CODE>.<P><H2><A NAME="SEC329" HREF="library_toc.html#SEC329" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC329">Non-Local Exits and Signals</A></H2><P>In BSD Unix systems, <CODE>setjmp</CODE> and <CODE>longjmp</CODE> also save andrestore the set of blocked signals; see section <A HREF="library_21.html#SEC368" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC368">Blocking Signals</A>.  However,the POSIX.1 standard requires <CODE>setjmp</CODE> and <CODE>longjmp</CODE> not tochange the set of blocked signals, and provides an additional pair offunctions (<CODE>sigsetjmp</CODE> and <CODE>sigsetjmp</CODE>) to get the BSDbehavior.<P>The behavior of <CODE>setjmp</CODE> and <CODE>longjmp</CODE> in the GNU library iscontrolled by feature test macros; see section <A HREF="library_1.html#SEC12" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_1.html#SEC12">Feature Test Macros</A>.  Thedefault in the GNU system is the POSIX.1 behavior rather than the BSDbehavior.<P>The facilities in this section are declared in the header file<TT>`setjmp.h'</TT>.<A NAME="IDX1448"></A><P><A NAME="IDX1449"></A><U>Data Type:</U> <B>sigjmp_buf</B><P>This is similar to <CODE>jmp_buf</CODE>, except that it can also store stateinformation about the set of blocked signals.<P><A NAME="IDX1450"></A><U>Function:</U> int <B>sigsetjmp</B> <I>(sigjmp_buf <VAR>state</VAR>, int <VAR>savesigs</VAR>)</I><P>This is similar to <CODE>setjmp</CODE>.  If <VAR>savesigs</VAR> is nonzero, the setof blocked signals is saved in <VAR>state</VAR> and will be restored if a<CODE>siglongjmp</CODE> is later performed with this <VAR>state</VAR>.<P><A NAME="IDX1451"></A><U>Function:</U> void <B>siglongjmp</B> <I>(sigjmp_buf <VAR>state</VAR>, int <VAR>value</VAR>)</I><P>This is similar to <CODE>longjmp</CODE> except for the type of its <VAR>state</VAR>argument.  If the <CODE>sigsetjmp</CODE> call that set this <VAR>state</VAR> used anonzero <VAR>savesigs</VAR> flag, <CODE>siglongjmp</CODE> also restores the set ofblocked signals.<P><P>Go to the <A HREF="library_19.html" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_19.html">previous</A>, <A HREF="library_21.html" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html">next</A> section.<P>

⌨️ 快捷键说明

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