Detail the error reporting errno and its associated application in C

  • 2020-04-02 03:17:57
  • OfStack

The use of error reporting in the C language standard library takes three forms.
1, errno
Errno in < Errno. H > Defined in the header file, as follows


#ifndef errno 
extern int errno; 
#endif 

The external variable errno holds the error code defined by the implementation in the library. Errno is usually defined as a macro starting with E in errno. H.
All error codes are positive integers, as in the following example


# define EDOM 33   

EDOM means that the parameter is not in a domain acceptable to a mathematical function, and this macro is used in a later example.
A common use of errno is to clear the library function before calling it and then check it later.

Errno is a useful tool when programming with the c language in Linux. He can keep the error code for the method that last called c. But if the c method is successfully called the last time, errno will not change. Therefore, errno is detected only when a c function returns a value exception.
Errno returns a number, each representing an error type. See the header file for details. The/usr/include/asm/errno. H
How do I convert the number of errno into the corresponding text?

A simple example


#include <stdio.h> 
#include <errno.h> 
#include <string.h> 
#include <math.h> 
 
int main(void) 
{ 
 errno = 0; 
 int s = sqrt(-1); 
 if (errno) { 
  printf("errno = %dn", errno); // errno = 33 
  perror("sqrt failed"); // sqrt failed: Numerical argument out of domain 
  printf("error: %sn", strerror(errno)); // error: Numerical argument out of domain 
 } 
 
 return 0; 

 

2, the strerror
The strerror in < String. H > , as follows
__BEGIN_NAMESPACE_STD  
 
Extern char *strerror (int * errnum) _throw;  
__END_NAMESPACE_STD  
The strerror function returns a pointer to an error message string whose contents are defined by the implementation. The string cannot be modified, but the strerror function can be overridden in subsequent calls.


char *strerror(int errno)

Usage:


fprintf(stderr,"error in CreateProcess %s, Process ID %d ",strerror(errno),processID)

Converts the error code to a string error message, which can be combined with other information to output to the user interface.
Note: assume that processID is an already obtained plastic ID

3, perror
Perror in < stdio.h > , as follows
__BEGIN_NAMESPACE_STD  
/* Print a message the meaning of the value of errno.
    This function is a possible cancellation point and therefore not
    Marked with __THROW.   * /  
Extern void perror (const char * * * s);  
__END_NAMESPACE_STD  
The function perror prints the following sequence in the standard error output stream: the parameter string s, the colon, the space, the error message containing the current error code in errno, and the newline character. In standard C, if s is a NULL pointer or a pointer to a NULL character, only the error message is printed, not the preceding parameter string s, colon, and space.


void perror(const char *s)

Function description
Perror () is used to output the cause of the error in the previous function to the standard error (stderr), and the string referred to by parameter s is printed first, followed by the error cause string. The reason for this error depends on the value of the global variable errno to determine the string to output.
Also, not all error messages from c function calls modify errno. For example, the gethostbyname function.
Is errno thread safe?
Errno is thread-safe and, in general, the compiler automatically guarantees errno security.
We look at the header file/usr/include/bits/errno. H
You'll see the following:


# if !defined _LIBC || defined _LIBC_REENTRANT

# define errno (*__errno_location ())
# endif
# endif 
#endif 

That is, errno is multi-threaded/process safe without defining either _LIBC_REENTRANT or _libc_libcant.
To check if your compiler defines the above variables, use the following simple program.


#include <stdio.h>
#include <errno.h>
 
int main( void )
{
#ifndef __ASSEMBLER__
  printf( "Undefine __ASSEMBLER__/n" );
#else
  printf( "define __ASSEMBLER__/n" );
#endif
 
#ifndef __LIBC
  printf( "Undefine __LIBC/n" );
#else
  printf( "define __LIBC/n" );
#endif
 
#ifndef _LIBC_REENTRANT
  printf( "Undefine _LIBC_REENTRANT/n" );
#else
  printf( "define _LIBC_REENTRANT/n" );
#endif
 
  return 0;
}

 


Related articles: