Unix, C, and C++
Function Reference
Errors

See notes on: Numeric Error Codes
              Detecting errors from mathematical functions
Nearly all unix system functions will return an int; the value is less than zero to indicate and error condition, and anything else (zero or positive) for success. The negative number returned is not a code signifying which error has occurred, it simply indicates that some error has occurred. When an error has been detected there are two generally useful functions for handling it:



  void perror(char * message)
      include: <stdio.h>
      The standard error message for the last error to have occurred
      during a system call (stored in the global int errno)
      is combined with the parameter 'message', and printed on
      the error output stream. message may be NULL.
      note Some network functions require use of herror instead.



  char * strerror(int errnum)
      include: <string.h>
      errnum = error number as found in errno
      Returns the standard error message for the error number provided.
      note Some network functions require use of hstrerror instead.



  extern int errno;
      include: <errno.h>
      This declaration gives programs direct access to the system-maintained
         global int that contains the most recently detected error. Including
         this definition of errno provides something that behaves like a variable,
         but may well not really be one.
      Errno is set when an error is detected, but is not set to zero when a system
         call is successful.
      note Some network functions require use of h_errno instead.



  int isnan(double x)
      include: <math.h>
      Returns 1 or true if x is Not-a-Number, 0 or false otherwise.
      note Does not detect infinities, use isinf for that
      See also Sample program



  int isinf(double x)
      include: <math.h>
      Returns 1 or true if x is positive or negative infinity, 0 or false otherwise.
      note Does not detect Not-a-Numbers, use isnan for that
      See also Sample program



  void herror(char * message)
      include: <netdb.h>
      The standard error message for the last error to have occurred
      during a call to gethostbyname or gethostbyaddr (stored in the 
      global int h_errno) is combined with the parameter 'message', 
      and printed on the error output stream. message may be NULL.



  char * hstrerror(int errnum)
      include: <netdb.h>
      errnum = error number as found in h_errno
      Returns the standard error message for the error number provided.



  extern int h_errno;
      include: <netdb.h>
      This declaration gives programs direct access to the system-maintained
      global int that contains the most recently detected error. Including
      this definition of errno provides something that behaves like a variable,
      but may well not really be one.
      note The network functions gethostbyname and gethostbyaddr require use
      of h_errno instead.





List of Numeric Error Codes

The file /usr/include/errno.h contains definitions of names for all the known error codes, for the current version running on rabbit (10th March 2003), these are the relevant definitions. Note that some of these are conditionally included, and depending upon compilation conditions may not all be defined in all programs. See the source file /usr/include/errno.h for exact details.
#define	EPERM		1		/* Operation not permitted */
#define	ENOENT		2		/* No such file or directory */
#define	ESRCH		3		/* No such process */
#define	EINTR		4		/* Interrupted system call */
#define	EIO		5		/* Input/output error */
#define	ENXIO		6		/* Device not configured */
#define	E2BIG		7		/* Argument list too long */
#define	ENOEXEC		8		/* Exec format error */
#define	EBADF		9		/* Bad file descriptor */
#define	ECHILD		10		/* No child processes */
#define	EDEADLK		11		/* Resource deadlock avoided; 11 was EAGAIN */
#define	ENOMEM		12		/* Cannot allocate memory */
#define	EACCES		13		/* Permission denied */
#define	EFAULT		14		/* Bad address */
#define	ENOTBLK		15		/* Block device required */
#define	EBUSY		16		/* Device busy */
#define	EEXIST		17		/* File exists */
#define	EXDEV		18		/* Cross-device link */
#define	ENODEV		19		/* Operation not supported by device */
#define	ENOTDIR		20		/* Not a directory */
#define	EISDIR		21		/* Is a directory */
#define	EINVAL		22		/* Invalid argument */
#define	ENFILE		23		/* Too many open files in system */
#define	EMFILE		24		/* Too many open files */
#define	ENOTTY		25		/* Inappropriate ioctl for device */
#define	ETXTBSY		26		/* Text file busy */
#define	EFBIG		27		/* File too large */
#define	ENOSPC		28		/* No space left on device */
#define	ESPIPE		29		/* Illegal seek */
#define	EROFS		30		/* Read-only file system */
#define	EMLINK		31		/* Too many links */
#define	EPIPE		32		/* Broken pipe */
#define	EDOM		33		/* Numerical argument out of domain */
#define	ERANGE		34		/* Result too large */
#define	EAGAIN		35		/* Resource temporarily unavailable */
#define	EWOULDBLOCK	EAGAIN		/* Operation would block */
#define	EINPROGRESS	36		/* Operation now in progress */
#define	EALREADY	37		/* Operation already in progress */
#define	ENOTSOCK	38		/* Socket operation on non-socket */
#define	EDESTADDRREQ	39		/* Destination address required */
#define	EMSGSIZE	40		/* Message too long */
#define	EPROTOTYPE	41		/* Protocol wrong type for socket */
#define	ENOPROTOOPT	42		/* Protocol not available */
#define	EPROTONOSUPPORT	43		/* Protocol not supported */
#define	ESOCKTNOSUPPORT	44		/* Socket type not supported */
#define	EOPNOTSUPP	45		/* Operation not supported */
#define	ENOTSUP		EOPNOTSUPP	/* Operation not supported */
#define	EPFNOSUPPORT	46		/* Protocol family not supported */
#define	EAFNOSUPPORT	47		/* Address family not supported by protocol family */
#define	EADDRINUSE	48		/* Address already in use */
#define	EADDRNOTAVAIL	49		/* Can't assign requested address */
#define	ENETDOWN	50		/* Network is down */
#define	ENETUNREACH	51		/* Network is unreachable */
#define	ENETRESET	52		/* Network dropped connection on reset */
#define	ECONNABORTED	53		/* Software caused connection abort */
#define	ECONNRESET	54		/* Connection reset by peer */
#define	ENOBUFS		55		/* No buffer space available */
#define	EISCONN		56		/* Socket is already connected */
#define	ENOTCONN	57		/* Socket is not connected */
#define	ESHUTDOWN	58		/* Can't send after socket shutdown */
#define	ETOOMANYREFS	59		/* Too many references: can't splice */
#define	ETIMEDOUT	60		/* Operation timed out */
#define	ECONNREFUSED	61		/* Connection refused */
#define	ELOOP		62		/* Too many levels of symbolic links */
#define	ENAMETOOLONG	63		/* File name too long */
#define	EHOSTDOWN	64		/* Host is down */
#define	EHOSTUNREACH	65		/* No route to host */
#define	ENOTEMPTY	66		/* Directory not empty */
#define	EPROCLIM	67		/* Too many processes */
#define	EUSERS		68		/* Too many users */
#define	EDQUOT		69		/* Disc quota exceeded */
#define	ESTALE		70		/* Stale NFS file handle */
#define	EREMOTE		71		/* Too many levels of remote in path */
#define	EBADRPC		72		/* RPC struct is bad */
#define	ERPCMISMATCH	73		/* RPC version wrong */
#define	EPROGUNAVAIL	74		/* RPC prog. not avail */
#define	EPROGMISMATCH	75		/* Program version wrong */
#define	EPROCUNAVAIL	76		/* Bad procedure for program */
#define	ENOLCK		77		/* No locks available */
#define	ENOSYS		78		/* Function not implemented */
#define	EFTYPE		79		/* Inappropriate file type or format */
#define	EAUTH		80		/* Authentication error */
#define	ENEEDAUTH	81		/* Need authenticator */
#define	EIDRM		82		/* Identifier removed */
#define	ENOMSG		83		/* No message of desired type */
#define	EOVERFLOW	84		/* Value too large to be stored in data type */
#define	ECANCELED	85		/* Operation canceled */
#define	EILSEQ		86		/* Illegal byte sequence */
#define	ELAST		86		/* Must be equal largest errno */
The file /usr/include/netdb.h contains definitions of names for all the known error codes for gethostbyname, for the current version running on rabbit (10th March 2003).
#define NETDB_SUCCESS   0	       	/* no problem */
#define HOST_NOT_FOUND  1 		/* Authoritative Answer Host not found */
#define TRY_AGAIN       2 		/* Non-Authoritative Host not found, or SERVERFAIL */
#define NO_RECOVERY     3 		/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
#define NO_DATA         4 		/* Valid name, no data record of requested type */
#define NO_ADDRESS      NO_DATA         /* no address, look for MX record */





Errors in Mathematical Functions

Mathematical functions generally do not detect errors no matter how sorely the programmer tempts them. The following program prints NO ERROR MESSAGES at all:
#include <stdio.h>
#include <math.h>

extern int errno;

void main(void)
{ errno=0;
  double x1 = sqrt(+1.2);
  if (errno!=0)
    perror("sqrt(+1.2)");
  else
    printf("sqrt(+1.2) = %f\n", x1);
  errno=0;
  double x2 = sqrt(-1.2);
  if (errno!=0)
    perror("sqrt(-1.2)");
  else
    printf("sqrt(-1.2) = %f\n", x2);
  errno=0;
  double x3 = asin(0.123);
  if (errno!=0)
    perror("asin(0.123)");
  else
    printf("asin(0.123) = %f\n", x3);
  errno=0;
  double x4 = asin(1.234);
  if (errno!=0)
    perror("asin(1.234)");
  else
    printf("asin(1.234) = %f\n", x4); }
The output produced should be:
sqrt(+1.2) = 1.095445
sqrt(-1.2) = NaN
asin(0.123) = 0.123312
asin(1.234) = NaN
The floating point processor has been left to take over responsibility for error handling. Programs wishing to detect errors must look at the results, and check that they are really numbers. (NaN means "Not a Number").

How are you supposed to do that? by using the almost-secret functions
isinf and isnan. By "almost-secret" I mean that the standard for C++ doesn't seem to have anything to say about the matter. Not-a-numbers are not comparable in the normal way:
  #include <stdio.h>
  #include <math.h>

  void main(void)
  { double error=sqrt(-1.0);
    double x=sqrt(-1.0);
    if (x==error)
      printf("Error!\n");
    else
      printf("All OK, the square root of -1 is %f\n", x); }
Fails to detect any error, and prints "All OK, the square root of -1 is NaN".

This oddness can be exploited. The test if (x!=x) ... comes out true if x is not-a-number (but not if it is an infinity). The correct test is:
  #include <stdio.h>
  #include <math.h>

  void main(void)
  { double x=sqrt(-1.0);
    if (isinf(x) || isnan(x))
      printf("Error!\n");
    else
      printf("All OK, the square root of -1 is %f\n", x); }
which correctly prints "Error!".

It is possible to arrange for interrupt signals to be generated on mathematical errors; it is very complex, but slightly more flexible.
see sample program




Interrupts for Mathematical Errors - Sample Program

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <machine/trap.h>
#include <ieeefp.h>

volatile int errorcode=0, errorsubcode=0;

void handler(int code, int subcode)
{ errorcode=code;
  errorsubcode=subcode; }

char *subname(int n)
{ switch (n)
  { case FPE_INTOVF: return "integer overflow";
    case FPE_INTDIV: return "integer divide by zero";
    case FPE_FLTDIV: return "floating divide by zero";
    case FPE_FLTOVF: return "floating overflow";
    case FPE_FLTUND: return "floating underflow";
    case FPE_FLTRES: return "inexact result";
    case FPE_FLTINV: return "invalid operation";
    case FPE_FLTSUB: return "subscript out of range";
    default: return "no detail"; } }

void printfperror(char * s)
{ if (errorcode==SIGFPE)
    fprintf(stderr, "%s: Floating Point Error - %s\n", s, subname(errorsubcode));
  else
    fprintf(stderr, "Wrong error code trapped\n"); }

void main(void)
{ signal(SIGFPE, (void (*)(int))handler);
  fpsetmask(FP_X_INV | FP_X_DNML | FP_X_DZ | FP_X_OFL | FP_X_UFL | FP_X_STK);
        // only FP_X_IMP has been left off.
  errorcode=0;
  double x1 = sqrt(+1.2);
  if (errorcode!=0)
    printfperror("sqrt(+1.2)");
  else
    printf("sqrt(+1.2) = %f\n", x1);
  errorcode=0;
  double x2 = sqrt(-1.2);
  if (errorcode!=0)
    printfperror("sqrt(-1.2)");
  else
    printf("sqrt(-1.2) = %f\n", x2);
  errorcode=0;
  double x3 = asin(0.123);
  if (errorcode!=0)
    printfperror("asin(0.123)");
  else
    printf("asin(0.123) = %f\n", x3);
  errorcode=0;
  double x4 = asin(1.234);
  if (errorcode!=0)
    printfperror("asin(1.234)");
  else
    printf("asin(1.234) = %f\n", x4);
  errorcode=0;
  double x5, x6=10.0;
  while (errorcode==0)
  { x5=x6;
    x6*=10.0; }
  printfperror("Stopped loop with");
  printf("Biggest power of ten is %.6e\n", x5); }
The output produced by this program is:
  sqrt(+1.2) = 1.095445
  sqrt(-1.2): Floating Point Error - invalid operation
  asin(0.123) = 0.123312
  asin(1.234): Floating Point Error - invalid operation
  Stopped loop with: Floating Point Error - floating overflow
  Biggest power of ten is 1.000000e+308