<

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x

Unique assertions

Published on
4,789 Points
1,689 Views
1 Endorsement
Last Modified:
Assertions are very helpful to find problems or bugs. But, sometimes there's a problem
using them, for example within a loop or a very often called function, because if such an
assertion fails it may happen that tons of assertion-dialogs pop up (at least in VC++
with 'ASSERT'-macro that's quite a mess).

The following macro can be used easily just the same way as VC++'s 'ASSERT'-macro or
CRT's 'assert'. To make its usage thread-safe first I introduce a simple class which does
synchronization using a mutex in Windows - if you want to use the macro with other
OS you'll have to adapt that class:

 
class Lock
{
	HANDLE	GetMutex()
	{
		static HANDLE hMutex = ::CreateMutex( NULL, FALSE, NULL );
		return hMutex;
	} 
public:
	Lock()
	{
		::WaitForSingleObject( GetMutex(), INFINITE );
	} 
	~Lock()
	{
		::ReleaseMutex( GetMutex() );
	}
};

Open in new window


Here's the macro itself:

 
// Handle the first time the assertion fails
#define assert_once_out_first( x ) \
	std::cout << __FILE__ << "(" << __LINE__ << "): first assertion for expression '" << #x << "'" << std::endl; 
// Handle further assertion fails
#define assert_once_out_next( x ) \
	std::cout << __FILE__ << "(" << __LINE__ << "): known assertion for expression '" << #x << "'" << std::endl; 
// Generates a file-wide unique variable name
#define assert_once_var __bAsserted__ ## __LINE__ ## __ 
// The unique assert macro
#define assert_once( x ) \
	do { \
		Lock _lock; \
		static bool assert_once_v = false; \
		if ( !(x) ) \
		{ \
			if ( !assert_once_v ) \
			{ \
				assert_once_v = true; \
				assert_once_out_first( x ); \
			} \
			else \
			{ \
				assert_once_out_next( x ); \
			} \
		} \
	} while ( 0 )

Open in new window


The usage is just simple, i.e.:

> int _tmain( int argc, char* argv[] )
> {
>      for ( int i = 0; i < 3; i++ )
>      {
>            assert_once( i < 2 );
>
>            for ( int j = 0; j < 3; j++ )
>            {
>                  assert_once( j % 2 != 1 );
>            }
>      }
>
>
>      return -1;
>}

The output will be:

> c:\test\testassert.cpp(15): first assertion for expression 'j % 2 != 1'
> c:\test\testassert.cpp(15): known assertion for expression 'j % 2 != 1'
> c:\test\testassert.cpp(11): first assertion for expression 'i < 2'
> c:\test\testassert.cpp(15): known assertion for expression 'j % 2 != 1'


For VC++ it's even simple to use the macros ASSERT and TRACE by just replacing these
two macros as shown here:

> #define assert_once_out_first( x ) \
>       TRACE( "%s(%d): Assertion for expression '%s'\n", __FILE__, __LINE__, #x ); \
>       ASSERT( x );
>
> #define assert_once_out_next( x ) \
>       TRACE( "%s(%d): Known assertion for expression '%s'\n", __FILE__, __LINE__, #x ); \
1
Author:Zoppo
2 Comments
LVL 40

Expert Comment

by:evilrix
Nice Zoppo. My only comment would be that as it stands this wouldn't be thread safe without additional mutual exclusion support.
0
LVL 31

Author Comment

by:Zoppo
Thanks, evilrix, and yes, you're right - I didn't add this because I wanted to keep the first version compiler-/platform independant.

I will think about how to do it best. In fact the implementation I implemented for use in my company is thread-safe.
0

Featured Post

Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month