GNU Info

Info Node: (com_err.info)Coding Conventions

(com_err.info)Coding Conventions


Next: Building and Installation Prev: Run-time support routines Up: Top
Enter node , (file) or (file)node

Coding Conventions
==================

   The following conventions are just some general stylistic conventions
to follow when writing robust libraries and programs.  Conventions
similar to this are generally followed inside the UNIX kernel and most
routines in the Multics operating system.  In general, a routine either
succeeds (returning a zero error code, and doing some side effects in
the process), or it fails, doing minimal side effects; in any event,
any invariant which the library assumes must be maintained.

   In general, it is not in the domain of non user-interface library
routines to write error messages to the user's terminal, or halt the
process.  Such forms of "error handling" should be reserved for
failures of internal invariants and consistancy checks only, as it
provides the user of the library no way to clean up for himself in the
event of total failure.

   Library routines which can fail should be set up to return an error
code.  This should usually be done as the return value of the function;
if this is not acceptable, the routine should return a "null" value,
and put the error code into a parameter passed by reference.

   Routines which use the first style of interface can be used from
user-interface levels of a program as follows:

     {
         if ((code = initialize_world(getuid(), random())) != 0) {
             com_err("demo", code,
                     "when trying to initialize world");
             exit(1);
         }
         if ((database = open_database("my_secrets", &code))==NULL) {
             com_err("demo", code,
                     "while opening my_secrets");
             exit(1);
         }
     }

   A caller which fails to check the return status is in error.  It is
possible to look for code which ignores error returns by using lint;
look for error messages of the form "foobar returns value which is
sometimes ignored" or "foobar returns value which is always ignored."

   Since libraries may be built out of other libraries, it is often
necessary for the success of one routine to depend on another.  When a
lower level routine returns an error code, the middle level routine has
a few possible options.  It can simply return the error code to its
caller after doing some form of cleanup, it can substitute one of its
own, or it can take corrective action of its own and continue normally.
For instance, a library routine which makes a "connect" system call to
make a network connection may reflect the system error code
`ECONNREFUSED' (Connection refused) to its caller, or it may return a
"server not available, try again later," or it may try a different
server.

   Cleanup which is typically necessary may include, but not be limited
to, freeing allocated memory which will not be needed any more,
unlocking concurrancy locks, dropping reference counts, closing file
descriptors, or otherwise undoing anything which the procedure did up
to this point.  When there are a lot of things which can go wrong, it
is generally good to write one block of error-handling code which is
branched to, using a goto, in the event of failure.  A common source of
errors in UNIX programs is failing to close file descriptors on error
returns; this leaves a number of "zombied" file descriptors open, which
eventually causes the process to run out of file descriptors and fall
over.

     {
         FILE *f1=NULL, *f2=NULL, *f3=NULL;
         int status = 0;
     
         if ( (f1 = fopen(FILE1, "r")) == NULL) {
             status = errno;
             goto error;
         }
     
         /*
          * Crunch for a while
          */
     
         if ( (f2 = fopen(FILE2, "w")) == NULL) {
             status = errno;
             goto error;
         }
     
         if ( (f3 = fopen(FILE3, "a+")) == NULL) {
             status = errno;
                 goto error;
         }
     
         /*
          * Do more processing.
          */
         fclose(f1);
         fclose(f2);
         fclose(f3);
         return 0;
     
     error:
         if (f1) fclose(f1);
         if (f2) fclose(f2);
         if (f3) fclose(f3);
         return status;
     }


automatically generated by info2www version 1.2.2.9