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.

Where Am I?

You are currently browsing the C++ category at JAWS.

Follow

Get every new post delivered to your Inbox.

Join 100 other followers