<

Unique assertions

Published on
4,741 Points
1,641 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
Comment
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

Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

Join & Write a Comment

Suggested Articles

The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
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