[C++] 63_C language exception handling

Posted by cx323 on Wed, 08 May 2019 17:57:03 +0200

exception handling

The concept of anomaly

  • Exceptions may occur during the execution of a program
  • The difference between Exception and Bug

    • Exceptions are the predictable branch of execution when a program runs
    • Bug is a bug in the program, an unexpected way to run

Comparison of Exception and Bug

  • abnormal

    • Runtime divides by zero
    • External files that need to be opened do not exist
    • Array access time crossing bounds
  • Bug

    • Use Wild Pointer
    • The heap array is not released after use
    • Selection sort cannot handle arrays of length 0

Ways of exception handling

Classical Processing of C Language

  • if ... else ...

void func(...)
{
    If (to determine whether an exception has occurred)
    {
        Normal code logic;
    }
    else
    {
        Exception code logic;
    }
}

Programming experiment: exception handling of division operation

#include <iostream>
#include <string>

using namespace std;

double divide(double a, double b, int* valid)
{
    const double delta = 0.00000000000001;
    double ret = 0;
    
    if( !((-delta < b) && (b < delta)) )
    {
        ret = a / b;
        
        *valid = 1;
    }
    else
    {
        *valid = 0;
    }
    
    return ret;
}

int main()
{
    int valid = 0;
    double r = divide(1, 0, &valid);
    
    if( valid )
    {
        cout << "r = " << r << endl;
    }
    else
    {
        cout << "Divided by zero ..." << endl;
    }
    
    return 0;
}
Output:
Divided by zero ...

defect

  • The divide function has three parameters, which make it difficult to understand its usage.
  • After the divide function is called, the result represented by valid must be judged.

    • When valid is true, the result is normal.
    • When valid is false, an exception occurs during the operation

Optimization through setjmp() and longjmp()

  • int setjmp(jmp_buf env)

    • Save the current context in the jum_buf structure with a return value of 0 (active call)
  • void longjmp(jum_env, int val)

    • Restore the context saved by setjmp() from the jmp_buf structure
    • Finally, it returns from the setjmp function call point with the return value of val.

Programming experiment: optimization of exception handling in division operation

#include <iostream>
#include <string>
#include <csetjmp>

using namespace std;

static jmp_buf env;

double divide(double a, double b)
{
    const double delta = 0.00000000000001;
    double ret = 0;
    
    if( !((-delta < b) && (b < delta)) )
    {
        ret = a / b;
    }
    else
    {
        longjmp(env, 1);
    }
    
    return ret;
}

int main()
{
    if( setjmp(env) == 0 )
    {
        double r = divide(1, 0);
    
        cout << "r = " << r << endl;
    }
    else
    {
        cout << "Divided by zero ..." << endl;
    }
    
    return 0;
}
Output:
Divided by zero ...

defect

  • Introduction of setjmp() and longjmp()

    • Inevitably involves the use of global variables
    • Violent jumps lead to reduced code readability
    • Essentially if... else... exception handling

It destroys the characteristics of structured programming: sequential execution, selective execution and circular execution.

The classical exception handling method in C language will mix a lot of exception handling code into program logic.

Normal logic code and exception handling code mix together, resulting in code expansion rapidly, difficult to maintain...

Example analysis

  • Analysis of exception handling code

#include <iostream>
#include <string>

using namespace std;

#define SUCCESS           0 
#define INVALID_POINTER   -1
#define INVALID_LENGTH    -2
#define INVALID_PARAMETER -3

int MemSet(void* dest, unsigned int length, unsigned char v)
{
    if( dest == NULL )
    {
        return INVALID_POINTER;
    }
    
    if( length < 4 )
    {
        return INVALID_LENGTH;
    }
    
    if( (v < 0) || (v > 9) )
    {
        return INVALID_PARAMETER;
    }
    
    unsigned char* p = (unsigned char*)dest;
    
    for(int i=0; i<length; i++)
    {
        p[i] = v;
    }
    
    return SUCCESS;
}

int main(int argc, char *argv[])
{
    int ai[5];
    int ret = MemSet(ai, sizeof(ai), 0);
    
    if( ret == SUCCESS )
    {
    }
    else if( ret == INVALID_POINTER )
    {
    }
    else if( ret == INVALID_LENGTH )
    {
    }
    else if( ret == INVALID_PARAMETER )
    {
    }
    
    return ret;
}

Question:
The reading volume is poor, and it is impossible to quickly determine which part of the normal logic code and which part of the abnormal logic code.

Summary

  • Unavoidable exceptions in the program
  • Exceptions are run-time problems that can be encountered during the development phase
  • Exceptions are handled by if... else... in C
  • There are better ways to handle exceptions in C++.

The above content refers to Ditai Software College Series Courses, please protect the originality.

Topics: C++ Programming C