How to add a Makefile post-build step

24 September, 2010 § 1 Comment

I spend most of my time working in Visual Studio and like its ability for performing post-build steps. These can be used to copy files, register DLLs, or run unit tests.

In my work at MSU I need to use a makefile and have been writing my code test-first. As such, I found I was spending a lot of time typing make and then typing ./runTests. Ideally, I could just have the tests run automatically after each build.

Looking around on the internet for quick steps to add a post-build step to make wasn’t so fruitful. I ran in to a bunch of old forum posts that mentioned Visual Studio-generated makefiles with post-build steps. A little thinking about the idea sprang the solution straight to mind.

It turns out it is really simple and quite intuitive. Here’s my current makefile:

CC=g++
CFLAGS=-c -Wall -pedantic-errors -Wextra -Wunused -Werror

all: findRoute findRoute-test runTests

rebuild: clean all

runTests: findRoute-test
	./findRoute-test.exe

findRoute: main.o cities.o flight_charges.o traffic_controller.o
	$(CC) main.o cities.o flight_charges.o traffic_controller.o -o findRoute

findRoute-test: main-test.o cities.o flight_charges.o traffic_controller.o
	$(CC) main-test.o cities.o flight_charges.o traffic_controller.o -o findRoute-test

main.o: main.cpp
	$(CC) $(CFLAGS) main.cpp

cities.o: cities.cpp
	$(CC) $(CFLAGS) cities.cpp

flight_charges.o: flight_charges.cpp
	$(CC) $(CFLAGS) flight_charges.cpp

traffic_controller.o: traffic_controller.cpp
	$(CC) $(CFLAGS) traffic_controller.cpp

main-test.o: main-test.cpp
	$(CC) $(CFLAGS) main-test.cpp

clean:
	rm -rf *o findRoute*

The runTests step above states that the findRoute-test step is a prerequisite. If that step passes, then it simply executes the next line, that being the test executable.

I found this very intuitive as it is no different than any other executable like the compiler. I hope this helps someone else who is thinking of doing the same or a variation.

Do you see anything above that could be improved? I love getting comments that help me get better.

Initializing an array in C++

16 June, 2010 § 6 Comments

Most people know about member initialization lists in C++. Initialization lists allow you to initialize a variable when the class is instantiated, versus assigning a value within the constructor.

Have you ever tried to initialize an array? Many websites will tell you that this is not possible. In fact, if you try this you’ll get a compiler error:

class array {
public:
  bool vars[2];
  array() : vars[0](true), vars[1](true) {}
};

BUT, if all you want to do is zero-initialize the array then you’re in luck! Simply place parens after the array and the array will be zero-initialized. Try out the code below:

#include <iostream>

class arrayInit {
 public:
  bool vars[2];

  arrayInit() : vars() {}
};

class array {
 public:
  bool vars[2];
  array() {}
};

int main()
{
  arrayInit a;
  std::cout << "a.vars[0] = " << a.vars[0] << std::endl;
  std::cout << "a.vars[1] = " << a.vars[1] << std::endl;

  array b;
  std::cout << "b.vars[0] = " << b.vars[0] << std::endl;
  std::cout << "b.vars[1] = " << b.vars[1] << std::endl;
}

Using code like this in Visual Studio can generate warning C4351 because the behavior is different from previous versions of VC++. Here is the documentation from MSDN:

Compiler Warning (level 1) C4351

new behavior: elements of array ‘array’ will be default initialized

When an array is in a constructor’s member initialization list, the elements of the array will be default initialized. In previous versions of Visual C++, when an array was in a constructor’s member initialization list, the elements of the array may not have been default initialized in some cases.

If the array’s element type does not have a constructor, the elements of the array will be initialized with the corresponding zero representation for that type.

C4351 means that you should inspect your code. If you want the compiler’s previous behavior, remove the array from the constructor’s member initialization list.

If you want the new behavior, which is likely, because the array was explicitly added to the constructor’s member initialization list, use the warning pragma to disable the warning. The new behavior should be fine for most users.

One situation where the new behavior can result in unexpected behavior is when placement new is used to construct the object that has the array as a member, and the program depends on the contents that the memory (for the elements of the default initialized array) had before the call to placement new. In this case, the older compiler would have left the contents of memory unchanged, but the new behavior will cause default initialization of the array elements, overwriting the original contents in memory.

Digraphs and trigraphs in C++

15 June, 2010 § Leave a comment

This is a guest blog post by A.J. Orians.

In C++ you can program using digraphs and trigraphs. They are character substitutions you can make that may be easier to type depending on your keyboard layout. For instance instead of the following code:

int main()
{
   int array[3];
   return 0;
}

Using digraphs and trigraphs it can be written as the following:

int main()
??<
   int array<:3:>;
   return 0;
??>

However Visual Studio will not compile using digraphs and trigraphs. But it is still important to know about them because you could be creating cross-platform code that may fail and it may not be easy to understand why. Take the following piece of code:

#include <vector>
using namespace std;

class A{};

int main()
{
   vector<::A> vect;
   return 0;
}

Under g++ it will fail to compile with the following error:

main.cpp: In function int main():
main.cpp:8: error: <:: cannot begin a template-argument list
main.cpp:8: note: <: is an alternate spelling for [. Insert whitespace between < and ::
main.cpp:8: note: (if you use -fpermissive G++ will accept your code)

The reason why is vect; which is an error. To fix this error just put a space between the < and the ::A.

Finding how a header file gets included

6 May, 2010 § 2 Comments

Have you ever had a header file generate warnings that is not explicitly part of your Visual Studio solution?

Recently I’ve been working on fixing static analysis warnings reported by Microsoft’s PREfast static analysis tool for C++. I ran in to an issue though with some of the Microsoft Windows SDK v6.0 headers. One file, aptly named `strsafe.h`, can be the cause for tons of warnings in a build.

I looked around and found that the Windows SDK team is fully aware of the problem. They recommend wrapping the include for strsafe.h with pragmas, like so:

#include <CodeAnalysis/warnings.h>
#pragma warning(push)
#pragma warning(disable: ALL_CODE_ANALYSIS_WARNINGS)
#include <strsafe.h>
#pragma warning(pop)

So the first thing I did was to search through my code and find out who what included strsafe.h. But it turns out that no file explicitly included it. I figured that it must get included from another include file.

To find out what files are included in your build, you can turn on /showIncludes through the Project Properties ➨ Configuration Properties ➨ C/C++ ➨ Advanced ➨ Show Includes

/showIncludes prints out a tree of all of the files that get included in when the project is built. Using this, I was able to find which SDK files we included that ended up including strsafe.h.

This process took me about a half hour in total from turning the compiler flag on, performing a rebuild, narrowing down the includes, and wrapping them with pragmas. I still got a nasty taste in my mouth for suppressing the warnings, but getting rid of them cut out a lot of noise surrounding actual warnings that are more pressing.

C++0x support in VC10 (VS2010)

15 February, 2010 § 4 Comments

I’ve been using Visual Studio 2010 since the Beta 2 release and just a couple days ago installed the Release Candidate.

VC10 has support for some of the features of C++0x and I wanted to get a head start on playing with the features so that when we switch production environments at work I will be ready to start taking advantage.

While getting to know VC10 and C++0x, I’ve noticed a couple low-severity issues that I wanted to point out:

Lambda Functions

Lambda functions allow you to create an inline functor. They don’t supply any new capabilities of the language, but they cut out a lot of noise. Here is an example usage:

std::vector<int> numbers;

numbers.push_back(1);
numbers.push_back(2);

std::for_each(numbers.begin(), numbers.end(), [](int number){ std::cout << number << std::endl; });

Pre-C++0x, you would have had to write this:

struct Functor {
  void operator()(int number) {
    std::cout << number << std::endl;
  }
};

std::vector<int> numbers;
numbers.push_back(1);
numbers.push_back(2);

std::for_each(numbers.begin(), numbers.end(), Functor());

The thing that I have noticed is that if you use using-declarations throughout your code, not all of them get captured from inside of the lambda. For example, this does not work:


void exampleFunction( const std::vector<int>& numbers ) {
using std::cout;
using std::endl;

std::for_each(numbers.begin(), numbers.end(), [](int number){ cout << number << endl; });

For some reason, endl is not captured, and the VC10 compiler throws an error. However, either of these do work:


void exampleFunction2( const std::vector<int>& numbers) {
  std::for_each(numbers.begin(), numbers.end(), [](int number){ std::cout << number << std::endl; });
}

// or

using namespace std;
void exampleFunction3( const std::vector<int>& numbers) {
  std::for_each(numbers.begin(), numbers.end(), [](int number){ cout << number << endl; });
}

Also, if the lambda-return-type-clause is not specified, then implicit type conversion warnings do not get generated:


std::deque<int> integers;
std::transform(numbers.begin(), numbers.end(), std::front_inserter(integers), [](int number){
  return number > 0 ? number / 2.0 : number * 2;  // no warning here
});

std::transform(numbers.begin(), numbers.end(), std::front_inserter(integers), [](int number) -> int {
  return number > 0 ? number / 2.0 : number * 2;  // warning C4244: 'return' : conversion from 'double' to 'int', possible loss of data
});

It doesn’t seem like the type inference is doing a great job with the compiler warning here. I would recommend explicitly specifying the lambda-return-type-clause to get full type checking by the compiler.

Using (return val of) member function as default parameter of member function

11 November, 2009 § 2 Comments

C++ allows the programmer to do some really cool things. When writing code I try to follow the Google C++ Style Guide, so I haven’t gotten much experience with the fringe areas of default parameters. A question was recently asked on the comp.lang.c++.moderated usenet group where the OP wanted to place a member function as the default argument, a la:

class foo {
 int getInteger();
 void doSomething(int i = getInteger()) { }
};

Many of the responses said that he should overload doSomething as a nullary function and call the original doSomething with the return value of the member function. Within most of these comments was one from Neil Butterworth, who mentioned that the reason this isn’t possible is because the this pointer is not available until the body of the function. He offered that the OP could make getInteger a static function.

class foo {
 static int getInteger();
 void doSomething(int i = getInteger()) { }
 };

And if you don’t believe him, you can use the Comeau C/C++ Online Compiler to see for yourselves.

I thought this was really cool. While I may not have a use for it at the moment, it is questions like these that are great conversation starters. About a month ago I subscribed to the clcm mailing list and I now recommend it to others as a way to learn different uses of C++ and interesting conversations about the language.

Compile-time virtual function calls in C++

21 August, 2009 § 7 Comments

C++ templates provide some really fascinating abilities, one of which is compile-time virtual function calls. WTL, the Windows Template Library, uses compile-time virtual function calls when deriving types. In this post, I will cover what I mean when I say “compile-time virtual function calls”, and how they create faster code and smaller executables.

By far, below is the most common use of templates within C++ code:

namespace std {
   template <typename T>
   class vector {
      /* ... */
   }
}
std::vector<int> primeNumbers;

But what if we wanted to derive our own type, with a templated class being the base type? See this example:

template <typename T>
class WindowImpl {
   int id_of_windowImpl;
   static LPCTSTR GetWindowCaption() { return NULL; }
   void DrawWindow() {
      LPCTSTR windowTitle = T::GetWindowCaption();
      /* Draw window and place title at top of UI */
   }
} 

Did you notice that there was no mention of the keyword virtual? This is where our little trick comes in. Let’s say we wanted to make our own boring derivation of Window, one that has the title of “Basic Window”. We could simply do this:

class BasicWindowImpl : WindowImpl<BasicWindowImpl> {
   int id_of_basicWindowImpl;
   static LPCTSTR GetWindowCaption() {
      return _T("Basic Window");
   }
}

BasicWindowImpl<BasicWindowImpl> basicWindow;

When the code is compiled, the static method GetWindowCaption will be called on the derived type. If the method isn’t implemented in the derived type, then the C++ lookup rules state that it will look deeper in the class and find the base implementation that returns NULL.

Also, this whole practice is made possible since immediately following the colon, the type has been declared and the typename can be used as a template parameter.

What does this mean in terms of efficiency/footprint?

First a short high level overview on how virtual functions are implemented. When a method inside of a class is declared virtual, a special data type is added to the class. This data type stores function offsets from the base of the class. When a call is made using a base type, this virtual function table (vftbl or vtable for short) is referenced and the memory address of the function is retrieved and executed.

Each instance of a class will hold a pointer to this table (often called a vpointer). This pointer is usually initialized at the end of the constructor by some hidden code that your C++ compiler generates.

On a 32-bit machine with 32-bit ints and no virtual functions: basicWindow is 8 bytes (4 bytes for each int that it holds).

On a 32-bit machine with 32-bit ints and virtual functions: basicWindow is 12 bytes (the same 8 bytes plus 4 bytes for the vpointer). Also, there is another 4 bytes used for the vtable and it’s one function pointer that is stored and pointing to BasicWindowImpl::GetWindowCaption.

In summary, by using compile-time virtual function calls, the sample code cuts it’s memory use in half. The vtable pointer does not consume much memory, but if there were 1,024 BasicWindowImpl instances created, then an extra 4kb of data would be unnecessarily used. Also, there is no need to look up the function address in the table due to the static linking of the overriden function at compile-time.

This brings you a smaller and faster executable by making your compiler work just a little harder.

Where Am I?

You are currently browsing entries tagged with c-plus-plus at JAWS.

Follow

Get every new post delivered to your Inbox.

Join 998 other followers