Exception handling in C language

Source: Internet
Author: User
Tags assert function prototype goto terminates throw exception try catch

A preface:

Exception handling is more familiar to developers who do object-oriented development, for example, in C #

Try

{

...

}

catch (Exception e) {...}

finally{

.....

}

In C + +, we often use the

try{}

...

catch () {}

Block for exception handling.

Said so much, so what is the exception to deal with it.

Exception handling (also known as error handling) provides a way to handle any unexpected or unusual situations that occur when a program is running.

Exception handling generally has two models, one is "terminate model", one is "recovery model"

Terminate model: In this model, it is important to assume that the error is so critical that the program cannot return to the place where the exception occurred. Once the exception is thrown, it indicates that the error is irreversible and cannot be returned to execution.

"Recovery Model": The exception handler's job is to fix the error, and then try to redeploy the problem method, and think two times to succeed. For the recovery model, it is usually desirable to continue executing the program after the exception is processed. In this case, throwing an exception is more like a call to a method--it can be configured in Java in such a way as to get a similar recovery behavior. (That is, instead of throwing an exception, the method is invoked to fix the error.) Alternatively, place the try block in the while loop, so that you can keep entering the try block until you get a satisfactory result.

Exception handling in two object-oriented objects

After a general understanding of what is exception handling, because exception handling in the object-oriented language is more commonly used, we first take C + + as an example, do a simple example of exception handling:

Question: Find the result of dividing two numbers.

Here, hide this error, that is, when the divisor is 0 o'clock, it will appear, so we have to use exception handling to catch the exception and throw exception information.

See the code specifically:

 #include <iostream> #include <exception> using namespace std;  Class Divideerror:public Exception {public:divideerror::D ivideerror (): Exception () {} const char*
         What () {return "attempts to remove a number with a value of 0";
 }
 
 }; 
     Double quotion (int numerator,int denominator) {if (0==denominator)//When divisor is 0 o'clock, throws an exception throw Divideerror ();    
 return static_cast<double> (numerator)/denominator;             int main () {int number1;             The first digit int number2;
     A second digit double result;
     cout<< "Please enter two digits:";
             while (cin>>number1>>number2) {try{result=quotion (number1,number2);
             
         cout<< "The result is:" <<result<<endl; //end Try catch (Divideerror &divexception) {cout<< "produces an exception:" <<d
         Ivexception.what () <<endl; }
     }
     
 }


In this example, we used the exception class in the <expection> header file and made the Divideerror class inherit it, while overloading the virtual method what () to give specific exception information.

and the exception handling class in C # encapsulates the more comprehensive, which encapsulates the commonly used exception handling information, here is not much to say.

Exception handling in the three-C language

There are generally several ways to handle exception handling in the C language:

1. The standard C library is provided with abort () and exit () two functions that can force the execution of the program to terminate its declaration in a <stdlib.h> header file.

2. Using an Assert macro call, located in the header file <assert.h>, a abort () is raised when the program fails.

3. Use the errno global variable, provided by the C Run-time library function, in header file <errno.h>.

4. Use the goto statement to jump when an error occurs.

5. Use setjmp,longjmp for exception handling.

Next, let's take a look at the various ways in turn:

We still take the exception of the previous processing divisor of 0 as an example.

1. Use the exit () function to terminate abnormally:

#include <stdio.h>
 #include <stdlib.h>
 double diva (double num1,double num2)         //Two number division function 
 {
     double re;
     re=num1/num2;
     return re;
 }
 int main ()
 {
    double a,b,result;
  printf ("Please enter the first number:");
   scanf ("%lf", &a);
   printf ("Please enter a second number:");
   scanf ("%lf", &b);
   if (0==b)                                //If divisor is 0 terminating program 
   exit (exit_failure);
 Result=diva (a,b);
    printf ("Dividing results:%.2lf\n", result);    
 return 0;
 }


Where exit is defined as follows:

_crtimp void __cdecl __mingw_nothrow exit (int) __mingw_attrib_noreturn;

Function prototype for exit: void exit (int) from this, we can also know that the Exit_failure macro should be an integer, the exit () function passed the parameter is two macros, one is just seen exit_failure, there is a exit_ Success can literally see that one is forced to terminate a program after an error, and one is that the program ends normally. They are defined as:

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

In this case, when the exception occurs, the program is terminated, but we do not capture the exception information, to capture the exception information, we can use the registration termination function atexit (), its prototype is this: Intatexit (atexit_t func);

Specifically look at the following procedures:

#include <stdio.h>
 #include <stdlib.h>
 void Exception (void)                           //Registration termination function, catch exception information 
 by hooking to this function {
     printf ("tries to divide by a number that is 0, an exception occurs.") \ n ");
 }
 int main ()
 { 
    double a,b,result;
   printf ("Please enter the first number:");
   scanf ("%lf", &a);
   printf ("Please enter a second number:");
   scanf ("%lf", &b);
   if (0==b)                    //If the divisor is 0 terminating the program and is attached to the registration function
   {
       
   atexit (Exception) that simulates the exception capture;                          
   Exit (exit_failure);
   } 
    Result=diva (a,b);
    printf ("Dividing results:%.2lf\n", result);    
 return 0;
 }


It should be noted here that the atexit () function is always executed, even if there is no exit () function, which is executed at the end of the program. Also, you can hook up multiple registration functions and execute them according to the stack structure. The abort () function is similar to the exit () function, which makes the program exit normally when an error occurs, and there is no more to say.

2. Use ASSERT () for exception handling:

ASSERT () is a macro that is used frequently when you debug a program, and remember that it is not a function that evaluates an expression in parentheses when the program runs, and if the expression is False (0), the program reports an error and terminates execution. If the expression is not 0, the following statement continues to execute. This macro usually determines whether there is a clear illegal data in the program, if the termination of the program to avoid serious consequences, but also easy to find errors.
Also note that the assert is valid only in the debug version and is ignored if compiled to release version.

We used an assert assertion to terminate an exception on the previous question: construct an assertion expression that could be faulted: assert (number. =0) Thus, when the divisor is 0, the expression is false, the program reports the error, and the execution terminates.

The code is as follows:

#include <stdio.h>
#include <assert.h>
double diva (double num1,double num2)         //Two number division function 
{
    double re;
    re=num1/num2;
    return re;
}
int main ()
{
  printf ("Enter the first number:");
  scanf ("%lf", &a);
  printf ("Please enter a second number:");
  scanf ("%lf", &b);
  ASSERT (0!=B);                                Constructs an assertion expression that captures the expected exception error
   Result=diva (a,b);
   printf ("Dividing results:%.2lf\n", result);    
   return 0;
}


3. Use errno global variables for exception handling:

errno global variables are mainly in the mode, when the system API function is abnormal, the errno variable is given an integer value, based on the view of the value to speculate on the cause of the error.

Each of these integer values has a corresponding macro definition that represents a different reason for the exception:

Code #define EPERM 1/* Operation not permitted */#define ENOFILE 2/* No such file or directory * * #define ENOENT 2 #define ESRCH 3/* No such process/#define EINTR 4/* Interrupt ed function call/#define EIO 5/* input/output error */#define ENXIO 6/* No such device or Address/#define E2BIG 7/* ARG list too long/#define ENOEXEC 8/* Exec Format Error/* * #de Fine EBADF 9/* Bad file descriptor * * #define ECHILD/No child processes/#define EAG AIN/* Resource temporarily unavailable/* #define ENOMEM/* Not enough spaces/* * #define E ACCES/* Permission denied//#define EFAULT////////* 15-unknown Error////////#defi     NE ebusy/* strerror reports "Resource Device" * * #define EEXIST/* File exists * * #define Exdev 18/* Improper link (cross-device link) */#define ENODEV/* No such device/#define ENOTDIR 20 /* Not a directory/#define EISDIR/is a directory */#define EINVAL/* Invalid Argu  ment/#define ENFILE/* Too many open files in System */#define EMFILE/* Too many Open Files/#define ENOTTY/* Inappropriate I/O control operation///* 26-unknown Error * * * * * #define EFB        IG/* File too large/* * #define ENOSPC/* No spaces left on device * * * #define Espipe        */* Invalid seek (seek on a pipe?)/#define EROFS/* read-only file System/#define Emlink */* Too many links/#define EPIPE/* Broken pipe/#define EDOM/* Domain err 
or (math functions)/#define ERANGE/* result too large (possibly too small)/* 35-unknown Error * *   #define Edeadlock /* Resource deadlock avoided (NON-CYG)/#define EDEADLK/* 37-unknown Error */#define Enametoo LONG/* Filename too long (in CYG?)/#define ENOLCK/* No locks available (in CYG?) * * * #d Efine Enosys/* Function not implemented (in CYG?) */#define ENOTEMPTY/* Directory not EM Pty (in CYG?)/#define EILSEQ/* Illegal byte sequence * *


Here we do not use the previous example of divisor 0 to do the exception processing, because I do not know how to define my own specific error errno, if any know, hope to give a method. I use an online example to illustrate how it is used:

Code 


#include <errno.h>  
#include <math.h>  
#include <stdio.h>  
int main (void)  
{  
errno = 0;  
if (NULL = = fopen ("D:\\1.txt", "RB"))  
{  
printf ("%d", errno);  
}  
else  
{  
 printf ("%d", errno);  
}  
return 0;  }


Here try to open a file D, if the file does not exist, this is to view the value of errno, the result is 2,

When a file exists, the errno value is the initial value of 0. Then look at the error message with the value 2, #define ENOFILE 2/* No such file or directory on the macro definition.
We know the cause of the mistake.

4. Use goto statement for exception handling:

Goto statement believe that everyone is familiar with a jump statement, we still use the divisor of 0 example, to construct an exception processing example:

Code 


#include <stdio.h>
double diva (double num1,double num2)         //Two number division function 
{
    double re;
    re=num1/num2;
    return re;
}
int main ()
{
  int tag=0;
  Double A,b,result;
  if (1==tag)
  {
      Throw:
    printf ("divisor is 0, exception \ n");
  }
   tag=1;
  printf ("Please enter the first number:");
  scanf ("%lf", &a);
  printf ("Please enter a second number:");
  scanf ("%lf", &b);
if (b==0)                                   //Catch an exception (perhaps that is not appropriate, for the moment)
  goto Throw;                                Throws an exception 
  Result=diva (a,b);
   printf ("%d\n", errno);
   printf ("Dividing results:%.2lf\n", result);    

return 0;
}


5. Use setjmp and longjmp for exception capture and processing:

setjmp and longjmp are non-local jumps, similar to goto jump function, but Goto statement has limitations, only in the local jump, when you need to jump to a function within the place when you need to use the setjmp and longjmp. The SETJMP function is used to save the run-time stack environment of the program, and the rest of the time, you can restore the previously saved program stack environment by calling the LONGJMP function. The basic method of exception handling:

Use setjmp to set up a jump point, and then call longjmp in other parts of the program to jump to that point (throw an exception).

The code looks like this:

#include <stdio.h>
#include <setjmp.h>
jmp_buf J;
void Exception (void)
{
   longjmp (j,1);
}
 Double Diva (Double num1,double num2)         //Two number division function
 {
    double re;
     re=num1/num2;
    return re;
}
 int main ()
{
    double a,b,result;

    
   printf ("Please enter the first number:");
   scanf ("%lf", &a);
   printf ("Please enter a second number:");
  if (setjmp (j) ==0)
  {
   scanf ("%lf", &b);
   if (0==b)
   Exception ();
 Result=diva (a,b);
    printf ("Division Results:%.2lf\n", result);
  }
  else
  printf ("Trying to divide by a number of 0");
 return 0;
}


Four summary:

In addition to the above several methods, there is also the use of semaphores and other methods for exception handling. Of course, in the actual development of each person has a variety of modes of skill, and this article is not to show that exception handling must do so, this is only a summary of the general practice, and do not use exception handling, if bad on the serious impact on the efficiency and structure of the program, like design patterns, can not be used indiscriminately.








































































Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.