Let’s Be Assertive

I find it fun to debug code. I add various printf() statements to a program to display values and quickly determine what’s going on. This process seems easier than toiling with a debugger.

For example, and especially with pointers, when I see a memory location changing between two functions, I use printf() statements to display the pointer’s memory address and value in each function:

printf("Address %p, Value %d\n",ptr,*ptr);

These statements help me unravel mysteries in the code and eventually fix the issue.

Another way to spot bugs in you code is to use assert().

The assert() macro is defined in the assert.h header. You may have seen it in some code samples, though most coders pull it out when they’re done testing. What assert() does is to perform a simple test, to verify a variable or condition. If the condition isn’t met (is false), the program halts.

In the following code, the assert() macro appears at Line 10. It tests the value of variable x. As long as x is less than 7, assert() is good with the code; the value is asserted to be less than 7. When x hits 7, however, the program halts.

#include <stdio.h>
#include <assert.h>

int main()
{
    int x;

    for(x=0;x<10;x++)
    {
        assert(x<7);
        printf("%d\n",x);
    }

    return(0);
}

Here’s a sample run:

0
1
2
3
4
5
6
Assertion failed: (x<7), function main, file 0714.c, line 10.
Abort trap: 6

I find the details displayed by the assert() macro to be most useful: The condition is displayed, (x<7); the function, main(); the filename, 0714.c, and best of all, the line number 10. (The text Abort trap may not appear in your output.)

You can deploy the assert() macro at various points of your code to ensure that variables are properly initialized. Even so, keep in mind that this macro is for your purposes as the programmer to aid in debugging. It's not intended to trap errors that a user may see.

For example, if a chunk of memory can't be allocated, I would use a standard if test instead of assert:

if(p==NULL)
/* DO handle condition here */

And not:

assert(p!=NULL);     /* DON'T */

Further, if you want to keep the assert() tests in your code, or you forget where they're located in some massive, multi-line program monster, you can disable them by adding the following constant definition:

#define NDEBUG

When NDEBUG is defined in your source code file, the assert.h header file rubs out the assert() macro definition. So you can switch assert() off by adding the above preprocessor directive or turn assert() back on by removing the line or commenting it out.

Consider the assert() macro yet another arrow in your C language debugging quiver.

3 thoughts on “Let’s Be Assertive

  1. Just out of idle curiosity what does Abort trap mean? Presumably the 6 is the last value of x before the assert fails? Does it appear only with certain compilers?

  2. It’s native to Darwin, the version of Unix that runs on a Mac. I don’t think it’s specific to any error condition, such as writing memory to a forbidden location. The documentation on Abort Trap 6 is rather slim.

  3. Thank you. I now know that I can safely forget about it 🙂

    It’s rare to find a Mac user who is willing to admit that the OS is just a version of Unix!

Leave a Reply