Saturday 12 November 2011

How do you get a program to tell you when (and where) a condition fails? in C programming

How do you get a program to tell you when (and where) a condition fails?

In any program, there are some conditions that should never occur. These conditions include division by
zero, writing to the null pointer, and so forth. You want to be informed whenever such conditions occur in
your program, and furthermore, you want know exactly where they occur.

The C language comes with such a construct, in the form of the assert() command. The assert()
command tests the condition inside its parentheses, and if the condition is false, it takes these steps:

1. Prints the text of the condition that failed.
2. Prints the line number of the error.
3. Prints the source code file that contains the error.
4. Causes the program to terminate with an error condition.

Stated succinctly, the assert() command is intended to ensure that conditions that should never occur do not. Take a look at what a few of these conditions might be. One of the most common problems is being unable to allocate memory. If the memory is absolutely needed and there is no way to free some, there is little choice but to leave the program. An assertion is a good way
to do this:
foo()
{
char *buffer;
buffer = malloc( 10000 );
assert( buffer != NULL );
}
This means that if buffer is ever equal to NULL, the program will terminate, informing the programmer of
the error and the line. Otherwise, the program will continue.
Another use of assert() might be this:
float IntFrac( int Num , int Denom )
{
assert( Denom != 0 )
return ( ( float ) Num ) / ( ( float ) Denom );
}

This use prevents the program from even dividing by zero.

It should be emphasized that assert() should be used only when the falsity of the condition would indicate catastrophic failure; if possible, the programmer should attempt to create code to handle the error more gracefully. In the preceding example, a special error value might be assigned to fractions with a zero denominator. This does not, however, mean that the assert() function is useless. A well-designed program should be full of asserts. After all, it is better to know that a disastrous condition is occurring than to be blissfully unaware of it (or, perhaps, unhappily aware!).

Another benefit of assert() is that by inserting the macro NDEBUG (no debugging) at the top of a program, you can cause all the asserts to be ignored during the compile. This is important for production versions of a program, after all the bugs have been fixed. You can distribute a version without the debugging code in the binary but, by removing the definition of NDEBUG, keep it in your version for debugging value. The code without all the tedious checks runs faster, and there is no chance of a customer’s program suddenly stopping because a variable has strayed slightly out of range.

Cross Reference:

XI.1: My program hangs when I run it. What should I do?
XI.3: What is the best way to debug my program?

No comments:

Post a Comment