Strange behavior with precompiled gcc headers

I was having trouble preparing the finished headers, so I came up with the following minimal working example.

This is the header file foo.h

 #include <iostream> using namespace std; void hello() { cout << "Hello World" << endl; } 

I will compile this since g++ -c foo.h gives me the compiled header foo.gch . I expect that when I compile the following source file including foo.h , it should select the header foo.h.gch , and I'm good.

 // test.cpp #include <cstdio> // Swap ordering later #include "foo.h" // ------------------ int main() { hello(); } 

But surprisingly, this does not compile using foo.h.gch , but uses foo.h To check, you can compile this as g++ -H test.cpp

However, if I reorder the included header files as follows:

 // test.cpp #include "foo.h" // ------------------ #include <cstdio> // Ordering swapped int main() { hello(); } 

Now, if I compile g++ -H test.cpp using g++ -H test.cpp , it compiles from foo.h.gch , whew!

So, I was wondering if this is a bug in GCC or should we use precompiled headers? In any case, I think this is useful to know.

+6
c ++ gcc precompiled-headers
Nov 15 '16 at 21:09
source share
3 answers

With GCC, precompiled headers only work if they are the only headers, and if they are included first (without the previous header).

This answer explains more why this is so. See also the chapter Precompiled Headers in the GCC documentation for:

  • A particular compilation can use only one precompiled header.
  • A precompiled header cannot be used after viewing the first C marker.

By the way, it may happen that pre-compiling some large header (especially in C ++) is not worth the effort. YMMV.

+4
Nov 15 '16 at 21:12
source share

On the GCC man page:

A precompiled header cannot be used as soon as the first C token is displayed.

So including <cstdio> in your precompiled header or including it will work first.

+4
Nov 15 '16 at 21:14
source share

In short, a precompiled header article works like this:

When you request the creation of a .pch file, the compiler processes the source file as usual. While he is doing this, his internal structures (mainly name tables and all related data) are populated. In the end, he takes a snapshot of these internal structures and saves it in a .pch file.

Later, when compiling a source file that contains a header for which a .pch file exists, the compiler can omit the expensive processing of the header file and load a ready-to-use snapshot from the '.pch' file.

Obviously, this can be done without affecting semantics only if:

  • the inclusion directive comes first;
  • compiler options are the same.

Everything that comes before the inclusion directive can:

  • add something to the compiler’s internal data structures;
  • affects the processing of the header file;
  • change the relationship between the entities described there.

Therefore, in this case, loading snapshots from internal data structures would be incorrect, because there would be no guarantee that they would leave these structures in the same state as after normal processing of the header.

+3
Nov 15 '16 at 21:40
source share



All Articles