Thomas Sampson


Leave a comment

Silencing ‘Unused Variable’ Warnings

Warnings generated by C++ compilers which inform you that your code has ‘unused’ or ‘unreferenced’ variables in undoubtedly a good thing. Warnings such as this usually suggest that a variable can be removed (perhaps it was a debug or temporary variable a frantic coder neglected to remove) or perhaps a variable which is not being properly assigned or accessed due to a typo or re-factoring cock-up. However there are instances where this kind of warning can prove troublesome, especially when warnings are treated as errors (a discipline I strongly advocate).

More specifically, this kind of warning can become difficult to cure within code heavily plagued with pre-processor conditions (either inlined or included via some ‘clever’ macro) which control which lines or sections of code are stripped and included under a projects often plentiful build configurations. Such mechanisms can prove very powerful, perhaps to strip all debug code from a particular build, or include specific code segments per platform. However code littered with nested conditional sections such as this often become messy and difficult to manage. As a result, some variables (which are in-fact referenced multiple times within the file) become un-referenced when building with a particular build configuration.

A Very Basic Example

Within the following code the msg variable is used within debug builds but becomes obsolete when carrying any non-debug build, yielding the compiler warning in question:

#include <stdio.h>

#if defined(_DEBUG)
#define DEBUG_PRINT( x ) printf((x));
#else
#define DEBUG_PRINT( x )
#endif

void main()
{
	const char* msg = "Some Debug Message";
	DEBUG_PRINT(msg);
}

The Solution?

In a case as simple as the above it might be tempting to checkout the DEBUG_PRINT macro and upon discovering that this macro only uses its parameter when _DEBUG is defined, nest the declaration of the msg variable within an identical conditional section. This will work perfectly in such a contrived scenario but when working with larger more complex codebases this approach can involve trawling through numerous nested macros and expansions, and may only fix the problem under a particular build configuration. Perhaps a better approach is to wrap the offending variable with the following macro which tricks the compiler into having used the variable under all build configurations (provided the macro is included within all build configurations of course).

#include <stdio.h>
#define ALWAYS_USE( x ) do { } while( &(x) != &(x) )

#if defined(_DEBUG)
#define DEBUG_PRINT( x )...
#endif

void main()
{
	const char* msg = "Some Debug Message"; ALWAYS_USE(msg);
	DEBUG_PRINT(msg);
}

The ALWAYS_USE macro shown above will make the compiler believe that the msg variable is always being used, however it’s contribution to the final executable should be non-existent when compiler optimisations are enabled (or at worst generate a NOP instruction on some compilers).

MSVC Generated Assembly NDEBUG (/O2)

void main()
{
    00F01000  xor   eax,eax 
    00F01002  ret
}


Leave a comment

Linking Debug Traces to Source Code

Today I discovered a nice little feature involving the Microsoft Visual Studio output window.

When emitting debug trace information from your application (using OutputDebugString), you can format your output string in such a way that when it is double-clicked in the output window, it jumps your code editor to the spot where it originated. The format which supports this feature is as follows:

%ABSOLUTE_FILE_PATH%(%LINE_NUMBER$): %MESSAGE%

So for example:

“C:/TextureManager.cpp(50): [TextureManager] Texture loaded!”

I often find myself copying a line from the output window and using CTRL+SHIFT+F (Find In File) to locate it’s origin. This is a nice way to get around that long winded process and provide a direct link to the file and line. You can of-course use the __FILE__ and __LINE__ pre-processor macros here to automatically format all your debug traces in this way.


Leave a comment

CallOnce

UPDATE: Modified the implementation to use singleton method access to CallOnce function map. Also added example of usage distributed across multiple source files.

CallOnce is a C++ technique I have picked up recently which allows code to be executed (usually to perform static initialisation or other housekeeping activities) before the program entry point (usually main). Rather than having some Init() method right at the beginning of the application which attempts to initialise all your static objects and data, the CallOnce mechanism allows each cpp file to register it’s own functions which gets called during global static initialisation (before the program entry point). This system is much cleaner and easier to manage, removing the requirement for a large central “Init()” function.

CallOnce can be implemented in various ways. In C++ global static initialisation order is undefined, for this reason additional levels of control can be added to the CallOnce implementation to define the order in which the registered functions get called (very important if there are dependencies between static objects and data). In this post I will keep things as simple as possible and use a couple of examples to demonstrate this technique.

Example 1

In this simple example a class “CallOnce” has a constructor which takes a function pointer (return type void, no parameters). In the constructor of the CallOnce class the function passed in gets called.
To use this system all that is required is to create some global instance of the CallOnce object and pass it the address of an initialisation function (in this case ::Init). The output proves that the Init function was in fact called before the program reached main.

Main.cpp

#include <stdio.h>

class CallOnce
{
	public:
		typedef void (*CallOnceFunc)(void);
		explicit CallOnce(CallOnceFunc func)
		{ func(); }
};

void Init()
{
	printf("Hello ");
}

const CallOnce gCallOnce( &Init);
int main(int argc, char* argv[])
{
	printf("World");
	return 0;
}

Output


> Hello World

Example 2

In this slightly more involved example, rather than immediately calling the function passed in the constructor, the function is inserted into a static map and stored there until CallOnce::Init() is called. When this happens, all of the registered functions get called in order of their priority (as std::map is automatically ordered by key and we store the priority value as the map key). By default all registering functions are given priority 1000 unless the overloaded constructor is used to specify a priority (in this system 0 = Highest priority). In the example shown below, even though Init1 is registered before Init2, due to the priorities specified they are executed in reverse order.

NOTE: The CallOnce instances do not all have to exist right before main, they can be scattered around your code base inside any cpp file you want.

CallOnce.h

#include <stdio.h>
#include <map>

class CallOnce
{
	public:
		typedef void (*CallOnceFunc)(void);
		typedef std::map<int, CallOnceFunc> FuncMap;

		explicit CallOnce(CallOnceFunc func)
		{
			static const unsigned int uDefaultPriority = 1000;
			GetFuncMap().insert(std::make_pair<int,CallOnceFunc>(uDefaultPriority, func));
		}
		explicit CallOnce(CallOnceFunc func, int iPriority)
		{
			GetFuncMap().insert(std::make_pair<int,CallOnceFunc>(iPriority, func));
		}
		static void Init()
		{
			FuncMap::const_iterator it(GetFuncMap().begin());
			for(; it != GetFuncMap().end(); ++it)
				(*it).second();
		}
	private:
		static FuncMap& GetFuncMap()
		{
			static FuncMap singleton;
			return singleton;
		}
};

Foo.cpp

#include "CallOnce.h"

void Init1() { printf("Init1 Called\r\n"); }
const CallOnce gCallOnce	 ( &Init1, 1);

Bar.cpp

#include "CallOnce.h"

void Init2() { printf("Init2 Called\r\n"); }
const CallOnce gCallOnceAgain( &Init2, 0);

Main.cpp

#include "CallOnce.h"

int main(int argc, char* argv[])
{
	CallOnce::Init();
	printf("Main Called");
	return 0;
}

Output


> Init2 Called

> Init1 Called

> Main Called


Leave a comment

Working in C!

This last week I have been treated to working on a code base written entirely in C code, no C++, all C!

While this has been an interesting challenge there are definitely times when I really missed some of the features provided in C++ and realised how much the standard template library is taken for granted! Anyway, as usual I only really post things on here which are of use to myself as reference at a later date, or items I found it particularly hard to track down elsewhere on the web. This post falls into both categories, and being such a fundamental issue I’m surprised that it took so long to find a solution.

I was working on adding a small lightweight XML library to the existing C code base. I was continuously faced with the problem of requiring some form of expandable buffer, in most cases to hold c strings (null terminated character arrays). The root of the problem is that there is no string type in C, no vectors and no dynamic arrays of any kind. This means that whenever you want to use one of the string functions such as strcopy,  strcat or sprintf, you are always required to know the size of the buffer upfront and allocate memory appropriately (freeing the memory when the buffer is disposed).

The main function I was concerned with was sprintf which I required in order to build up strings for the xml documents. The length of the strings produced by sprintf could be very varied and picking a fixed buffer size would in most cases be over the top, and in some cases dangerous as buffer overflows could potentially always occur, corrupting the heap. Luckily I discovered the following technique which allows you to first print the formatted string to a dummy file (no data is actually written to a file and no I/O occurs) using fprintf. Once the fprintf call has completed (assuming the format string / parameters were valid) you can then check the return value to find out exactly how many characters were written to the dummy buffer, providing you with the exact buffer size required for allocation!

Once a buffer of the correct size is allocated sprintf can then be used with the same paramaters to safely fill in the buffer. This method does have its drawbacks. I guess that there is extra overhead incurred in formatting the string twice and gaining a handle to the dummy file. However, as far as I can find this is the only way to do this properly without using fixed size buffers. One work of warning, this technique should work across platforms but “:NULL” should be replaced with “nul” on unix systems. A simple #ifdef UNIX should sort that out!

FILE* f = fopen(":NULL","w");

char* buffer = 0;

int n = fprintf(f,"hello %s", "world");

buffer = (char*)malloc(n);

sprintf(buffer, "hello %s", "world");

//use buffer

free(buffer);