Parabellum Games

Using asserts for debugging

The C and C++ assert is a macro used to test code by programmers to ensure that parts of the code is working as the programmer oringinal intended. Below is an example of the syntax:

Code:
// C code
#include <assert.h>
assert( /*expression*/ );
Code:
// C++ code
#include <cassert>
assert( /*expression*/ );

“expression” can be any boolean expression, x > y, functionName() == 21, etc. If the expression is true, the assert passes and the program carries on as normal. If it is false, it stops the execution of the program and if you are debugging, it sets the debugger at the point where the assert failed.

Asserts can and should be used anywhere that has a possible fail case, such as an object going out of possible bounds of the world, moving at impossible speeds and pointers that are invalid when they should not be.

There are other ways that programmers use to find this information such as printing values to the screen but the problem is that when the error occurs, the program is still running. The programmer usually doesn’t have any more information about the state of the program to work out why it has occurred.

Most programmers won’t even start printing values to the screen unless they have noticed something has gone wrong such as the program crashing. They then insert the debugging code where they think the cause of error is and attempt to recreate the problem to see if they can find any anomalies.

At the same time, it isn’t possible to print the entire state of the program on screen without clutter. With asserts, you can literally litter the code with them, safe in the knowledge that as soon as the program reaches an invalid state, they will fire.

The crash itself (if you are lucky) can happen nowhere near actual cause of the crash. This is a common symptom of buffer overruns or memory ’stomps’.

The fact asserts stops execution and sets the debugger where the assert failed is important because it allows the programmer to look at the state of the object and program to help work out why it reached an invalid state.

Consider the following code:

Code:
class Foo
{
	public:
		char AccessAt( int index )
		{
			return mArray[index];
		}
	private:
		static const int MAX_SIZE = 10;
		char mArray[MAX_SIZE];
};

Hopefully, most of you will recognise where the code can go drastically wrong so let’s put in some asserts to emphasise this:

Code:
class Foo
{
	public:
		char AccessAt( int index )
		{
			assert( index < MAX_SIZE );
			assert( index >= 0 );
			return mArray[index];
		}
	private:
		static const int MAX_SIZE = 10;
		char mArray[MAX_SIZE];
};

Now when the program attempts to access an element outside the bounds of the array, one of those asserts will fire and then the callstack in the debugger can be used to find out which section of code was the cause. In the worse case scenario, the programmer at least has a starting point in hunting the cause of the error.

Code:
#0 0x9003d66c	kill() (??:??)
#1 0x9010e8cf	raise() (??:??)
#2 0x9010d422	abort() (??:??)
#3 0x1e1d	__eprintf() (/Users/SYau/Work/SandboxCpp/main.cpp:26)
#4 0x1f60	Foo::AccessAt(this=0xbffffc16, index=10)
( /Users/SYau/Work/SandboxCpp/main.cpp:8 )
#5 0x1db5	RandomFunction()
( /Users/SYau/Work/SandboxCpp/main.cpp:20 )
#6 0x1dc3	main()
( /Users/SYau/Work/SandboxCpp/main.cpp:25 )

To disable these checks as these asserts decrease runtime performance and at the same time, you don’t want your end users to use any debug code, you can define the macro NDEBUG before you include the assert.h/cassert header or in the project/makefile settings.

Code:
// C
#define NDEBUG
#include <assert.h>
Code:
// C++
#define NDEBUG
#include <cassert>

The following article looks at extending the power of an assert further and is definitely worth a read (warning: requires understanding of the preprocessor): Stupid C++ tricks: Adventures in Assert

Asserts are a powerful and cheap tool to employ for programmers to use and there is little excuse not to use them in your own code.

4 Responses

Subscribe to comments with RSS.

  1. [...] 16, 2008 Just finished writing a small article aimed at the homebrew community on using asserts: Using asserts for debugging. Posted by yaustar Filed in Articles, Homebrew Development Tags: article, asserts, [...]

  2. Protector one said, on July 3, 2008 at 12:10 pm

    Hey that’s pretty cool! I wonder if python has something similar… I’m all too familiar with the ‘print clutter’ you mention. :)

  3. yaustar said, on July 3, 2008 at 12:32 pm

    Looks like they do: http://www.agapow.net/programming/python/asserts

  4. Protector one said, on August 25, 2008 at 11:20 am

    Sweet!


Leave a Reply