3 clever macros

Today, I will show you three, clever macros. Thanks to them we can get rid of several problems. Full code and an example, as usual, are available on CWorking.

First macro: LOG

#ifdef DEBUG_MODE
#define LOG(stream, pattern, params...) fprintf( stream,"%20s:%3u | " pattern "\n", __FILE__, __LINE__, ##params )
#else
#define LOG(stream, dummy, params...)
#endif

I recommend to use it especially with the DEBUG_MODE flag connected to the makefile. Thanks to that we could switch off the logger e.g by changing the project build mode from “debug” to “release”. Logger syntax is the same as fprintf, but it prints not only a formatted string, but also a filename and a line number where logger was called. It is very helpful if we want to find a source of a specific log entry. All logs can be gathered in a log file, stdout, stderr etc. thanks to the “stream” variable.

Next look at the MALLOC which might be used instead of simple malloc function.

/** Allocate memory */
void* CW_allocate_memory( CW_uint32_t CW_memory_size, const char* CW_file, CW_uint32_t CW_line );

/** MALLOC macro which should be used instead of malloc */
#define MALLOC( block_type, blocks_number ) (block_type*)CW_allocate_memory( ( blocks_number )* sizeof( block_type ), \
		                                                                     __FILE__, __LINE__ );
/* --------- *.c file --------- */

void* CW_allocate_memory( CW_uint32_t CW_memory_size, const char* CW_file, CW_uint32_t CW_line )
{
	/* Trace - it can be called in case error e.g out of memory */
	LOG( stderr, "Info: MALLOC called from %s %u", CW_file, CW_line );

	/* Allocate memory */
	void* p = malloc( CW_memory_size );
	if(p == NULL)
	{
		LOG( stderr, "Out of memory: MALLOC called from %s %u", CW_file, CW_line );
		exit(EXIT_FAILURE);
	}

	/* Initialize memory block to zero */
	memset( p, 0, CW_memory_size );

	/* Return memory block */
	return p;
}

Using this macro we don’t need to remember about a type casting and the type size. We have to provide only a typename and a number of memory blocks (eg. array size). Our code will be more readable. Furthermore, we don’t need to worry that our variable won’t be initialized. It is important especially for the embeeded systems. Moreover, our program will inform us about the “out of memory” error. I also connect the MALLOC macro with the logger, so it is possible to print an information about the place where specific MALLOC was called. It might be useful for debugging purposes.

The last macro I want to describe is FREE. It will free a memory allocated by MALLOC macro.

/** Free memory */
void CW_free_memory( void** CW_pointer, const char* CW_file, CW_uint32_t CW_line );

/** FREE macro which should be used instead of free */
#define FREE( pointer ) CW_free_memory( &pointer, __FILE__, __LINE__ );

/* --------- *.c file --------- */

void CW_free_memory( void** CW_pointer, const char* CW_file, CW_uint32_t CW_line )
{
	/* Trace - it can be called in case error e.g null pointer exception */
	LOG( stderr, "Info: FREE called from %s %u", CW_file, CW_line );

	/* Check if not null */
	if ( (*CW_pointer) == NULL )
	{
		LOG( stderr, "Null pointer exception: FREE called from %s %u", CW_file, CW_line );
		exit(EXIT_FAILURE);
	}

	/* Free memory */
	free( (*CW_pointer) );

	/* Reset to NULL */
	( *CW_pointer ) = NULL;
}

Beside the freeing memory, this macro will validate the input pointer and assign the output to NULL. It is also possible to print an information about the place where FREE macro was called.

Each macro should be used consciously because C is not very safe programming language. We could add some macro and didn’t even notice that macro with the same name, but different functionality exists.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s