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:
// C code #include <assert.h> assert( /*expression*/ );
// 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:
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:
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.
#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.
// C #define NDEBUG #include <assert.h>
// 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.
[...] 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, [...]
Hey that’s pretty cool! I wonder if python has something similar… I’m all too familiar with the ‘print clutter’ you mention.
Looks like they do: http://www.agapow.net/programming/python/asserts
Sweet!