Detecting Superfluous #Includes in C/C++

Detecting superfluous #includes in C/C++?

It's not automatic, but doxygen will produce dependency diagrams for #included files. You will have to go through them visually, but they can be very useful for getting a picture of what is using what.

Tools to find included headers which are unused?

DISCLAIMER: My day job is working for a company that develops static analysis tools.

I would be surprised if most (if not all) static analysis tools did not have some form of header usage check. You could use this wikipedia page to get a list of available tools and then email the companies to ask them.

Some points you might consider when you're evaluating a tool:

For function overloads, you want all headers containing overloads to be visible, not just the header that contains the function that was selected by overload resolution:

// f1.h
void foo (char);

// f2.h
void foo (int);


// bar.cc
#include "f1.h"
#include "f2.h"

int main ()
{
foo (0); // Calls 'foo(int)' but all functions were in overload set
}

If you take the brute force approach, first remove all headers and then re-add them until it compiles, if 'f1.h' is added first then the code will compile but the semantics of the program have been changed.

A similar rule applies when you have partial and specializations. It doesn't matter if the specialization is selected or not, you need to make sure that all specializations are visible:

// f1.h
template <typename T>
void foo (T);

// f2.h
template <>
void foo (int);

// bar.cc
#include "f1.h"
#include "f2.h"


int main ()
{
foo (0); // Calls specialization 'foo<int>(int)'
}

As for the overload example, the brute force approach may result in a program which still compiles but has different behaviour.

Another related type of analysis that you can look out for is checking if types can be forward declared. Consider the following:

// A.h
class A { };

// foo.h
#include "A.h"
void foo (A const &);

// bar.cc
#include "foo.h"

void bar (A const & a)
{
foo (a);
}

In the above example, the definition of 'A' is not required, and so the header file 'foo.h' can be changed so that it has a forward declaration only for 'A':

// foo.h
class A;
void foo (A const &);

This kind of check also reduces header dependencies.

How should I detect unnecessary #include files in a large C++ project?

While it won't reveal unneeded include files, Visual studio has a setting /showIncludes (right click on a .cpp file, Properties->C/C++->Advanced) that will output a tree of all included files at compile time. This can help in identifying files that shouldn't need to be included.

You can also take a look at the pimpl idiom to let you get away with fewer header file dependencies to make it easier to see the cruft that you can remove.

C / C++ clearer #includes

You can pass include directories to your compiler. The configuration depends on the compiler. For gcc you set an include directory with -I. https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html

Why doesn't the compiler need to be passed the respective source files when including headers from the standard library?

When you have a header file called foo.h it doesn't necessarily mean that the there should be a source file associated with it called the foo.c. There can be be independent source and header files.

When you do compile a simple C code, hello_world.c

#include <stdio.h>
int main() {
// printf() displays the string inside quotation
printf("Hello, World!");
return 0;
}

And when you compile the code, the code is first preprocessed as part of this the header file inclusion happens and any header file that is to be included and is present within the </> (#include <stdio.h> in our case) is searched for it's definition in the current directory and a few predefined search path already know to the compiler (the preprocessor). Few of the standard header file definitions are present such as /usr/include, /usr/local/include, etc. more info

The second part of your question being as to how does the compiler know the definition of say for example printf() when we don't associate a source file at compile time that is cause when you compile any program the compilers by default links it with a std C library called the libc which contains the definition of functions such as scanf,printf,etc



Related Topics



Leave a reply



Submit