Topic : C Lessons
Author : Christopher Sawtell
Page : << Previous 17  
Go to page :


label.
  2 ) The setjump / longjmp library routines.

  The concept of the go to a label construction has had reams of literary
verbiage written about it and this author does not intend to add to the pile.
Suffice it to say that a goto is a necessary language construct. There are a
few situations which require the language to have ( in practice ) some form of
unconditional jump. Treat this statement with great caution if you wish your
code to be readable by others. An example of legitimate use.

  for ( a = 0; a < MATRIX_SIZE; a++ )
  {
    for ( b = 0; b < MATRIX_SIZE; b++ )
    {
      if ( process ( matrix, a, b )) goto bad_matrix;
      }
     }
   return ( OK );

bad_matrix:

   perror ( progname, "The data in the matrix seems to have been corrupted" );
   return ( BAD );


  This is one of the very few "legitimate" uses of goto, as there is no
"break_to_outer_loop" in `C'. Note that some compilers complain if the label
is not immediately followed by a statement. If your compiler is one of these
naughty ones, you can put either a `;' or a pair of braces `{}' after the
`:' as a null statement.

  An example of a program package which makes extensive use of the goto is the
rz and sz modem communications protocol implementation by Chuck Forsberg of
Omen Technology. You should download it and study the code, but do remember
that the proof of the pudding argument must apply as the rz & sz system has
become extremely popular in its application because it works so well.

  The other method of changing program flow is the setjump and longjmp pair of
library functions. The idea is to provide a method of recovery from errors
which might be detected anywhere within a large program - perhaps a compiler,
interpreter or large data acquisition system. Here is the trivial example:

#ident "set_jmp_demo.c"

#include <stdio.h>
#include <setjmp.h>

jmp_buf save;

main()
{
  char c;

  for ( ;; )                     /* This is how you set up a continuous loop.
*/
  {
    switch ( setjmp( save ))
    {
case 0:
      printf ( "We get a zero returned from setjmp on setup.\n\n");
      break;                   /* This is the result from setting up. */

case 1:
      printf ( "NORMAL PROGRAM OPERATION\n\n" );
      break;

case 2:
      printf ( "WARNING\n\n" );
      break;

case 3:
      printf ( "FATAL ERROR PROGRAM TERMINATED\n\nReally Terminate? y/n: " );
      fflush ( stdout );
      scanf ( "%1s", &c );
      c = tolower ( c );
      if ( c == 'y' ) return ( 1 );
      printf ( "\n" );
      break;

default:
      printf ( "Should never return here.\n" );
      break;
      }
    process ();
    }
  }

process ()
{
  int i;

  printf ( "Input a number to simulate an error condition: " );
  fflush ( stdout );
  scanf ( "%d", &i );
  i %= 3;
  i++;                /* So that we call longjmp with  0 < i < 4 */
  longjmp ( save, i);
  }


  Although in this silly little demo the call to longjmp is in the same file
as the call to setjmp, this does not have to be the case, and in the practical
situation the call to longjmp will be a long way from the call to setjmp. The
mechanism is that setjmp saves the entire state of the computer's CPU in a
buffer declared in the jmp_buf save; statement and longjmp restores it exactly
with the exception of the register which carries the return value from longjmp.
This value is the same as the second argument in the longjmp call - i in our
little demo. This means, of course, that the stack and frame pointer registers
are reset to the old values and all the local variables being used at the time
of the longjmp call are going to be lost forever. One consequence of this is
that any pointer to memory allocated from the heap will also be lost, and
you will be unable to access the data stored in the buffer. This is what the
jargonauts call "memory leakage", and is really very difficult bug to find.
Your program runs out of dynamic memory long before it should. Take care.
So you have to keep a record of the buffers' addresses and free them
before the call to longjmp.

More details later on when we learn about the heap memory allocation routines.

Copyright notice:-

(c) 1993 Christopher Sawtell.

I assert the right to be known as the author, and owner of the
intellectual property rights of all the files in this material,
except for the quoted examples which have their individual
copyright notices. Permission is granted for onward copying,
but not modification, of this course and its use for personal
study only, provided all the copyright notices are left in the
text and are printed in full on any subsequent paper reproduction.

+----------------------------------------------------------------------+
| NAME   Christopher Sawtell                                           |
| SMAIL  215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
| EMAIL  chris@gerty.equinox.gen.nz                                    |
| PHONE  +64-3-389-3200   ( gmt +13 - your discretion is requested )   |
+----------------------------------------------------------------------+



Page : << Previous 17