How to use "C language notes" assert?

2020/02/0312:58:08 technology 2378

1. What is assert()?

When writing code, we always make some assumptions. Asserts are used to capture these assumptions in the code. Assertions can be regarded as an advanced form of exception handling. Z3z

assertions are expressed as Boolean expressions that the programmer believes to be true at a certain point in the program. You can enable and disable assertion verification at any time, so you can enable assertions during testing and disable assertions during deployment. Similarly, after the program is put into operation, the end user can re-enable assertions when they encounter problems.

Note that assert() is a macro, not a function.

2. How to use assert?

1, the header file and prototype where assert is located

In the MinGW tool, the assert() macro exists in the header file assert.h, and its key content is as follows:

ifdef NDEBUGdefine assert(x)((void)0)else /* debugging enabled */_CRTIMP void __cdecl __MINGW_NOTHROW _assert (const char*, const char*, int) __MINGW_ATTRIB_NORETURN;define assert(e) ((e)? (void)0: _assert(e, __FILE__, __LINE__))endif/* NDEBUG * The /

assert() macro accepts an integer expression parameter. If the value of the expression is false, the assert() macro will call the _assert function to print an error message in the standard error stream, and call abort() (the prototype of the abort() function is in the stdlib.h header file) function termination program.

When we think that the program bug has been eliminated, we can write the macro definition define NDEBUG in front of the position where assert.h is included.

Tips:

  • __cdecl is the abbreviation of C Declaration (declaration, declaration), which means the default function call method of C language: all parameters are pushed into the stack from right to left.
  • _CRTIMP is the abbreviation of C run time implement, meaning the realization of C run time library. As user code, this thing should not be used. The prompt is whether to use the dynamic C runtime library of dll or a macro of the statically linked C runtime library.
ifndef _CRTIMPifdef _DLLdefine _CRTIMP __declspec(dllimport)else /* ndef _DLL */define _CRTIMPendif /* _DLL */endif /* _CRTIMP */
  • __MINGW_NOTH These are the identifiers of abnormal handling and related standard files in the __MINGWzAT31 CRTIMP All are useful, but we don't need to care. From the perspective of our users, the above function prototypes are regarded as: void _assert(const char*, const char*, int);

    2, assert application

    assert is mainly used for type checking and unit testing.

    unit testing (unit testing) refers to the inspection and verification of the smallest testable unit in the software. For the meaning of a unit in a unit test, generally speaking, the specific meaning should be determined according to the actual situation. For example, a unit in C language refers to a function.

    (1) Example 1: Division operation

    /*Compiler tool: mingw32 gcc6.3.0*/include include int main(void){int a, b, c;printf("Please enter the value of b, c:");scanf("%d %d", &b, &c);a = b / c;printf ("a = %d", a);return 0;}

    Here, the variable c as the denominator cannot be equal to 0. If we enter 2 0, what will be the result? The result is that the program will jump:

    How to use

    In this example, there are only a few lines of code. We can quickly find that the reason for the program jump is that the value of the variable c is 0. However, if the amount of code is large, can we find the problem so quickly?

    At this time, assert() comes in handy. In the above code, we can add assert(c) before the code a = b / c;; this code is used to judge the validity of the variable c. At this point, compile and run again, and the result is:

    How to use

    is visible, and the program will also print an error message in the standard error stream:

    Assertion failed: c, file hello.c, line 12

    This message contains some errors We look for information that is helpful for bugs: the problem lies in variable c, on line 12 of the hello.c file. In this way, we can quickly locate the problem. At this time, a careful friend of

    will find that in our introduction to assert() above, there is such a statement: If the value of the expression is false, the assert() macro will call the _assert function to print one in the standard error stream Error message, and call abort() (the prototype of the abort() function is in the stdlib.h header file) function to terminate the program.

    So, for our example, our assert() macro can also be replaced with the following code:

    if (0 == c){puts("The value of c cannot be 0, please re-enter!"); abort( );}

    This can also give us a hint:

    How to use

    However, using assert() has at least a few advantages:

    1) can automatically identify the file and the line number that has the problem.

    2) The assert mechanism can be turned on or off without changing the code (whether it is turned on is related to the size of the program). If you think that the program bug has been eliminated, you can write the following macro definition before the position containing assert.h:

    define NDEBUG

    and recompile the program, so that the editor will disable all assert() statements in the project file. If the program has problems again, you can remove this define instruction (or comment it out), and then recompile the program, so that the assert() statement can be re-enabled.

    (2) Example 2: STM32 library function

    Let’s take a look at the familiar GPIO initialization function:

    How to use

    . As you can see, in the implementation of this function, there are three statements such as assert_param(), whose role is to perform some function entry parameters. Validity check. In fact, assert_param() is similar to assert() in our C standard library. For the stm32f10x series, it is defined in the file stm32f10x_conf.h:

    How to use

    This is an example. In addition to the GPIO initialization function, other functions in the STM32 firmware library function will do such parameter checks.

    Third, the comparison between assert and if? The assertion function of

    assert() seems to be able to be realized with if, but there is still a difference between the two. Let's take a look at the difference:

    first look at an example, we use mThe alloc function defines a variable in the heap space. How should we define it and how to do some defensive processing?

    First of all, we need to know that malloc function returns a pointer to the allocated memory if the memory is allocated successfully (the initial value in this storage area is uncertain), otherwise it returns a null pointer NULL. Look at the following code:

    int* p = (int*)malloc(sizeof(int)); assert(p);/* error example */

    is there any problem with writing this way?

    seems to be fine, but the problem is big! Our assert() will be disabled after we finish debugging, so the above code is equivalent to only the following sentence:

    int* p = (int*)malloc(sizeof(int)); 

    At this time, when we Malloc can't apply for memory space when the program is running, and if some solutions are not done, fatal errors may occur.

    We should rewrite the above code as:

    int* p = (int*)malloc(sizeof(int)); if (NULL == p) /*Please use if to judge, it is necessary*/{ /* Do some processing*/}


    Let’s take a look at the usage differences between assert and if for error-proofing:

    1, assert statements are used in debug version debugging; if(NULL!=p) is used to check pointers in release version Validity;

    2, assert are generally used to check the legality (validity) of function parameters instead of correctness, but legal programs are not necessarily logically correct programs, and if judgments are used, they still have to be processed. .

    is also used by assert to check whether some unallowable situations have occurred during debugging. Once they happen, it indicates that our program is likely to have BUG, ​​and if judges the various situations that we should handle, and these situations If it happens, it does not mean that the program has a BUG.


    4. _Static_assert (C11 standard)

    assert() is checked at runtime. If a project is large, it will take a long time to compile. In some cases, checking at runtime may result in low efficiency.

    _Static_assert() comes in handy at this time. This is a feature in the C11 standard. _Static_assert() is checked at compile time. If some exceptions in the code are detected at compile time, the program will fail to compile . Let’s look at an example:

    /*Compilation environment: mingw32 gcc6.3.0 Compilation command: gcc -std=c11 hello.c -o hello.exe*/include include  /*CHAR_BIT is a macro in limits.h*/ _Static_assert(CHAR_BIT == 16, "16-bit char falsely assumed");int main(void){printf("Welcome to follow the embedded hodgepodge! See more notes\n");return 0;}

    _Static_assert accepts two parameters , The first parameter is an integer constant expression, and the second parameter is a string. If the first expression is 0, the second parameter string will be output when compiling, and the compilation fails. The compiling result of the program

    is as follows:

    How to use

    is visible, the compilation error is reported, and the print prompts our problem, and the string of the second parameter of our _Static_assert is printed, so that we can quickly locate the cause of the compilation error The problem is.

    The above is some summary notes about assert() assertion macro, if there is an errorWelcome to point out!

technology Category Latest News

Qilu.com·Lightning News July 15th For Hexagon, which is among the Hurun Global 500, it is more of a solution provider for smart manufacturing and smart cities than a high-tech listed company. To be more relevant - at the Hexagon Smart Industrial Park in Qingdao, staff showed repo - DayDayNews

Qilu.com·Lightning News July 15th For Hexagon, which is among the Hurun Global 500, it is more of a solution provider for smart manufacturing and smart cities than a high-tech listed company. To be more relevant - at the Hexagon Smart Industrial Park in Qingdao, staff showed repo

Five years of breakthroughs: Qingdao | Provides technical services for 95% of the world’s cars and 90% of aircraft, revealing the driving force behind this Qingdao company’s intelligent manufacturing