C Standard Library & lt; assert. h & gt; Implementation

Source: Internet
Author: User

URL: http://www.cnblogs.com/archimedes/p/c-library-assert.html.

1. Background Knowledge

The only purpose of the header file <assert. h> is to provide the assert macro definition, which can be used for assertions in key areas of the program. If an asserted proves to be untrue, you want the program to output an appropriate prompt in the standard error stream and terminate the execution.

You can write the code as follows:

#include<assert.h>...assert(0 <= i && i < sizeof(a) / sizeof(a[0]));

Of course, the above Code is not the best form in practice. The exceptional termination of the program should be changed to the recovery of some errors.

Macro NDEBUG

You can define the macro NDEBUG in some places of the program to change the assert expansion mode.

If NDEBUG is not defined for a place in the program that contains assert, the header file defines the macro assert as an active form and can be expanded into an expression, test the assertion and output an error message when the assertion is false, and the program ends. If NDEBUG is defined, the header file defines this macro as a static form without any operations.

2. Use of <assert. h>

From the code above, we can see that a simple predicate can be used to simplify assert:

If (! OK) abort (); // declare it in the header file <stdlib. h>

If you think there is no need for assertions, add the following code before including the header file:

# Define NDEBUG // cancel assertion # include <assert. h>

Different methods can be used to control assertions in the entire source file. When assertions occur within a frequently executed loop, the performance may drop sharply or before reaching the suggestive part, an earlier asserted may terminate the program. To enable assertions, you can write:

#undef NDEBUG#include<assert.h>

To disable assertions, you can write:

#define NDEBUG#include<assert.h>

Note: even if the macro NDEBUG has been defined, we can still define it safely, which is a benign redefinition.

3. Implementation of <assert. h>

According to the above analysis, the general framework of this header file is as follows:

# Undef assert // remove defined # ifdef NDEBUG # define assert (expr) (void) 0) // function failure # else # define assert (expr )... # endif

A Simple Method for writing macro assert activities is as follows:

#define assert(expr) if(!(expr)) \    fprintf(stderr, "Assertion failed: %s, file %s, line %i\n", \        #expr, __FILE__, __LINE__)

This method is unacceptable for the following reasons:

1. Macros cannot directly call any output functions of the database.

The above definition contains fprintf, stderr, and other functions or macros defined in stdio. h. The program may not contain this header file.

2. The macro must be extended to a void expression.

3. Macros should be able to be extended to effective and compact code

In this version, a function with five parameters is always called.

The modified assert macro is as follows:

#undef assert#ifdef NDEBUG    #define assert(expr)  ((void) 0)#else    void __bad_assertion (const char *_mess);    #define    __str(x)    # x    #define    __xstr(x)    __str(x)    #define    assert(expr)    ((expr)? (void)0 : \                __bad_assertion("Assertion \"" #expr \                    "\" failed, file " __xstr(__FILE__) \                    ", line " __xstr(__LINE__) "\n"))#endif

Here, _ LINE _ is a built-in macro that represents the row number of the code for this row. Because _ LINE _ is not extended to the string literal, it becomes a decimal constant, converting it to an appropriate form requires an additional processing layer. Add two hidden macros _ str and _ xstr to the header file. One macro replaces _ LINE __with its decimal constant extension __, the other is to convert a decimal constant into a string literal.

Implementation of the hidden library function _ bad_assertion called by a macro:

#include<assert.h>#include<stdio.h>#include<stdlib.h>void __bad_assertion(const char *mess) {        fputs(mess, stderr);        abort(); }

Function _ bad_assertion uses two other library functions by calling <stdio. h> the function fputs declared in writes the string to the standard error stream and terminates the program execution with abort exceptions. The relevant header files will be analyzed in detail later.

4. <assert. h> Test
# Include <assert. h> # include <stdio. h> # include <stdlib. h> int main (void) {FILE * fp; fp = fopen ("test.txt", "w"); // open a FILE in writable mode, create a file with the same name as assert (fp) if it does not exist; // No error is found here: fclose (fp); fp = fopen ("noexitfile.txt", "r "); // open a file in read-only mode. If the file does not exist, assert (fp) fails to be opened. // The fclose (fp) error occurs here ); // The program will never be executed here to return 0 ;}

Note:

1. Check the validity of input parameters at the beginning of the function, for example:

Int resetBufferSize (int nNewSize) {// function: Change the buffer size, // parameter: New length of the nNewSize buffer // return value: current length of the buffer // description: nNewSize <= 0 indicates clearing the buffer assert (nNewSize> = 0); assert (nNewSize <= MAX_BUFFER_SIZE );...}

2. Each assert tests only one condition, because when multiple conditions are verified simultaneously, if the assert fails, you cannot intuitively determine which condition fails, for example:

Assert (nOffset> = 0 & nOffset + nSize <= m_nInfomationSize); // poor // good assert (nOffset> = 0); assert (nOffset + nSize <= m_nInfomationSize );

3. You cannot use statements that change the environment, because assert takes effect only on DEBUG. If you do so, problems will occur when the program is actually running, such:

Error:

assert(i++ < 100);

This is because if an error occurs, for example, I = 100 before execution, this statement will not be executed, and the I ++ command will not be executed.

Correct:

assert(i < 100);i++;

4. The assert and subsequent statements should be empty in a row to form a logical and visual sense of consistency.

5. In some cases, assert cannot replace conditional filtering.

References

C Standard Library

 

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.