Monday, May 1, 2017

Assertions in C - Pre, Post, Invariants.

In C, assertions are implemented with the standard assert macro. The argument to assert must be true when the macro is executed, otherwise the program aborts and prints an error message. For example, the assertion

    assert( size <= LIMIT );
will abort the program and print an error message like this:

    Assertion violation: file tripe.c, line 34: size <= LIMIT
if size is greater than LIMIT.

There are 3 types of assertions

1. Preconditions : Specify conditions at the start of a function.
2. Postconditions : Specify conditions at the end of a function.
3. Invariants : Specify conditions over a defined region of a program.

An assertion violation indicates a bug in the program. Thus, assertions are an effective means of improving the reliability of programs-in other words, they are a systematic debugging tool.

Preconditions

Preconditions specify the input conditions to a function. Here is an example of a function with preconditions:

int
magic( int size, char *format )
{
    int maximum;

    assert( size <= LIMIT );
    assert( format != NULL );
    ...
These pre-conditions have two consequences:

magic is only required to perform its task if the pre- conditions are satisfied. Thus, as the writer of magic, you are not required to make magic do anything sensible if size or format are not as stated in the assertions.
The caller is certain of the conditions under which magic will perform its task correctly. Thus, if your code is calling magic, you must ensure that the size or format arguments to the call are as specified by the assertions.


Postconditions

Postconditions specify the output conditions of a function. They are used much less frequently than preconditions, partly because implementing them in C can be a little awkward. Here is an example of a postcondition in magic:

    ...
    assert( result <= LIMIT );
    return result;
}
The postcondition also has two consequences:

magic guarantees that the stated condition will hold when it completes execution. As the writer of magic, you must make certain that your code never produces a value of result that is greater than LIMIT.
The caller is certain of the task that magic will perform (provided its preconditions are satisfied). If your program is calling magic, then you know that the result returned by magic can be no greater than LIMIT.
Compare this with the apple-picker analogy. Another part of your contract states that you will not bruise the apples. It is therefore your responsibility to ensure that you do not (and if you do, you have failed.) Your employer is thus relieved of the need to check that the apples are not bruised before shipping them.

Assert Writing preconditions

The simplest and most effective use of assertions is as preconditions-that is, to specify and check input conditions to functions. Two very common uses are to assert that:

Pointers are not NULL.
Indexes and size values are non-negative and less than a known limit.
Each assertion must be listed in the Asserts section of the function description comment in the corresponding header file. For example, the comment describing magic will include:

 *  Asserts:
 *      'size' is no greater then LIMIT.
 *      'format' is not NULL.
 *      The function result is no greater than LIMIT.
 */
If there are no assertions, write ``Nothing'':

 *  Asserts:
 *      Nothing
 */

Assertion violations

If a precondition is violated during program testing and debugging, then there is a bug in the code that called the function containing the precondition. The bug must be found and fixed.

If a postcondition is violated during program testing and debugging, then there is a bug in the function containing the precondition. The bug must be found and fixed.


Turning assertions off

By default, ANSI C compilers generate code to check assertions at run-time. Assertion-checking can be turned off by defining the NDEBUG flag to your compiler, either by inserting

    #define NDEBUG
in a header file such as stdhdr.h, or by calling your compiler with the -dNDEBUG option:

    cc -dNDEBUG ...
This should be done only you are confident that your program is operating correctly, and only if program run-time is a pressing concern.

If you face any error like this while compiling the code, make sure you have #include included.


error: implicit declaration of function 'assert' is invalid in C99 [-Werror,-Wimplicit-function-declaration]

references:
http://ptolemy.eecs.berkeley.edu/~johnr/tutorials/assertions.html

No comments:

Post a Comment