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
}
Advertisements


Leave a comment

C++ Inline keyword

Today I came across the inline keyword in c++. The inline keyword can be placed before a function defenition and is usually placed before functions which contain only a few lines of code.

If you have written a function which is only 3 lines of code for example, and these 3 lines of code are fairly simple and non resource-expensive, some compilers will automatically inline your function. However, the inline keyword is a way of enforcing that this happens at compile time. So what is function inlining?

Function inlining allows the compiler to substitute any calls to your function with the actual function definition it’s self. Let’s say you have a call to a function go(). Without function inlining, at runtime all sorts will go off. Register values, any paramaters and the instruction pointer will be pushed onto the stack (time consuming), the instruction pointer pointed to the location of the function, the function executes then all values are popped off of the stack!

If your function is a large complex algorithm which only gets executed a couple of times in the program, and needs keeping seperate for clarity, then this is not such a problem. However if your function is small and gets called repeatedly throughout the program, function inlining allows those few lines of code, to replace the original call to the function. For example,

Without function inlining…

void go()
{
    cout << "Hello World";
    cout << "Test function!";
}
int main()
{
    for(int i( 0);i<10;++i)
    {
        go(); // Standard call mechanism initiated
    }
}

With function inlining enforced…..

inline void go()
{
    cout << "Hello World";
    cout << "Test function!";
}
int main()
{
    for(int i( 0);i<10;++i)
    {
        cout << "Hello World"; //Gets inserted at compile time
        cout << "Test function!"; //Gets inserted at compile time
    }
}

Although many factors contribute towards the performance of a program, inlining can be used to bring about significant performance increases if used properly.


3 Comments

Dynamic Arrays in C++

Update: After looking back at this post I realised that the title “Dynamic Arrays in C++” is pretty misleading, I think this was basically way back when I figured out how do do memory allocation! For anyone looking to do real dynamic arrays / collections, consider the std::vector class or use a linked list.


C++I have only started using C++ properly over the past few months and I’m realising that many of the features and aspects I took for granted in interpreted languages, are implemented in a much more complicated way in c++!

For example if you wanted to create a dynamic array in c# (as below) the .NET framework will do all the memory allocation and management for you and let you initialise an array of your chosen size at run time (when the size of the array cannot be determined at compile time)

int[] temp = new int[varName] //Where varName could be an integer given by the user


Another interesting point at this stage is that after c# initialises the array dynamicaly, for example with a dimension of 3. When you try and access temp[20] for example, the .net framework instantly detects you are breaching the size of the array and throws an “Out of bounds” exception. However in c++ (and this applies to static and dynamic arrays) accesing a position outside the array simply looks up in memory PAST the array and starts reading random data, not even necessarily from your application!

Anyway, to make a dynamic array in c++ we must follow 3 steps

  1. use the new keyword to initialise the array in memory
  2. ensure that the memory allocation for the array was successfull, catching the failure of this event
  3. delete the array from memory after use (as c++ will not dispose of it automatically)

The example below simply gets a number from the user and then initialises an array with the dimension the user has specified.


int mySize( 0);
cin >> mySize;
int* myArray = new int[mySize];
if(myArray!=0)
{
  //catch failure of array initialisation
}
else
{
  //Work with array....
  delete[] myArray;
}