Weird Behavior with gcc precompiled headers - c++

I was having troubles getting pre-compiled headers to work, 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 compile this as g++ -c foo.h gives me a compiled header foo.gch. I expect that when I compile the following source file that includes foo.h, it should pick the header foo.h.gch and I am 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 rather uses foo.h. To verify you can compile this as g++ -H test.cpp
However, if I change the order of included header files as follows:
// test.cpp
#include "foo.h" // ------------------
#include <cstdio> // Ordering swapped
int main() {
hello();
}
Now if I compile using g++ -H test.cpp, it compiles from foo.h.gch, whew!
So I was wondering if this is a bug in GCC or are we supposed to use pre-compiled headers like that? In either case I think its useful to know..

With GCC, precompiled headers work only if they are the only header, and if they are included first (without any previous header).
This answer explains more why it is so.
See also the Precompiled headers chapter of GCC documentation, which says:
Only one precompiled header can be used in a particular compilation.
A precompiled header can't be used once the first C token is seen.
BTW, it could happen that pre-compiling some large header (notably in C++) is not worth the effort. YMMV.

In a nutshell, the precompiled header thing works thus:
When you request to create a '.pch' file, the compiler processes the source file as usual. While it does so, its internal structures (mostly, name tables and all associated data) are populated. At the end, it makes a snapshot of these internal structures and saves it to the '.pch' file.
Later, when compiling a source file that includes a header for which a '.pch' file exists, the compiler can omit the expensive processing of the header file and load the ready-for-use snapshot from the '.pch' file instead.
Obviously, this can be done without affecting the semantics only if:
the inclusion directive comes before anything else;
the compiler options are the same.
Anything that comes before the inclusion directive may:
add something to the internal data structures of the compiler;
affect the processing of the header file;
alter relations between entities described there.
Therefore, in this case, loading the snapshot of internal data structures would be wrong because there'd be no guarantee that it would leave these structures in the same state as after the normal processing of the header.

From the GCC manual pages:
A precompiled header can't be used once the first C token is seen.
So including <cstdio> in your precompiled header or including it first will work.

Related

gcc precompiled header: pragma once in main file

I created a header file. Something simple as follows.
#pragma once
#include <iostream>
template<typename T>
void say(T t) {
std::cout << t << std::endl;
}
and then use g++ to create the gch pre-compiled header with g++ hello.h. It gives me this warning ->
pch.h:2:9: warning: #pragma once in main file
2 | #pragma once
| ^~~~
But the gch file created and the pre-compiled header works fine. This error goes away if I use header guards.
Am I doing something wrong here?
You're not doing anything wrong; this is a quality of implementation issue that has been mentioned on the issue tracker before (but, to my knowledge, there are currently no plans to change the behaviour).
In Clang, you could turn off the warning for that particular compiler invocation (with -Wno-pragma-once-outside-header); in GCC you'll just have to grin and bear it for now.
The main source file used to generate a precompiled header is usually a made-up "indirect" header that contains only a bunch of #include for all the actual real headers you want to precompile.
When you use the machinery this way, there is no need for a #pragma once (nor guard) in the main file, and hence it works as intended with no warning.
This is a known GCC bug:
Pragma once warning when compiling PCH
To my knowledge, there is no good way to disable this warning. One way that retains matching behavior is an additional indirection. In pch.h, use
#include <pch-real.h>
(without #pragma once), and store the actual header contains in pch-real.h. This mostly preserves the include-only-once optimization even if <pch.h> is included multiple times in non-PCH mode.

one or more multiply defined symbols found error - simple

I'm trying to deal with this problem for some time and I can't seem to find the solution. I'm getting error:
one or more multiply defined symbols found
I faced this error while dealing with something more complicated, but even simple examples like this one don't work for me. Here is my main.cpp:
#include "defs.cpp"
int main()
{
string a = "A";
printIt(a);
}
, and here is my defs.cpp:
#include "header.h"
void printIt(string a)
{
cout << a;
}
, and this is my header.h:
#include <string>
#include <iostream>
using namespace std;
void printIt(string a);
I guess this is something trivial, but please don't rage if you think this is duplicate, because I'm a beginner and I didn't understand more complicated examples. Some help would be appreciated.
When you see #include "defs.cpp" you need to get very suspicious: cpp files are not meant to be included; only header files are designed for that.
Instead of including a cpp file, write a header for it. It appears that you have a suitable header already - your header.h, which contains the forward declaration of printIt:
void printIt(string a);
Now replace #include defs.cpp with #include "header.h", and compile your code. This should fix the problem.
Compiling this depends on the system where you are trying it out. On UNIX-like systems, you would write
g++ defs.cpp main.cpp
./a.out
You should not #include a CPP file. Only include header files containing the function prototype definitions. If no such header file exists, put the function prototype in your program (for eg. in file where main is written).
In your case, you are including (directly/indirectly) the CPP file which is having the definition of the function. Since same definition is compiled through CPP files, compiler is putting them into .OBJ file (known as intermediate or object files). The linker finally attempts to combine these Object files, and says some function (symbol) is multiply defined.
In main.cpp you are including defs.cpp which includes a definition of printIt. So the translation unit corresponding to main.cpp defines printIt.
However, you are also compiling defs.cpp which defines printIt. defs.cpps corresponding translation unit thus defines printIt too.
Combining both into one program would lead to multiple (yet equivalent) definitions of this function which is forbidden by the ODR. Remove the #include directive and your program should link correctly.
This is because you are including:-
#include "defs.cpp"
and due to this there are multiple definitions of method printIt.
These are some basic rules:-
1) You must always include only header files in your source files. Even then you have to make sure header files are included only once because if it is included more than once then there could again be problem of multiple definition.To protect against that your header files should contain header gaurds.
2) C++ always adheres with single definition rule. However , you can have as many declaratons as possible as long as all declarations are consistent.

Checking header file for dependencies at compile-time

Do compilers offer the capability to automatically check if each source file (and its associated header file, if any) include all other headers that are required? Or at least issue a warning, say, if a required header is not included explicitly?
For example, I would like the compiler to report when I do something like this:
header1.h
#include <string>
...
header2.h
#include "header1.h"
#include <iostream>
std::string blah; //<-- issue warning here, <string> not included explicitly
...
source2.cpp
#include "header2.h"
...
cout << endl; //<-- issue warning here, <iostream> not included explicitly
I am using g++ and Visual Studio, so my question primarily applies to these compilers. Thanks!
There is no automatic way for doing so, as far as I know.
My suggestion is to confine inclusions into headers only to what is needed for the "interface" defined in the .h
In C++ Coding Standards (Sutter, Alexandrescu) you can find an item which tackles this explicitly (it's titled Make header files self-sufficient). I cite:
Behave responsibly: Ensure that each header you write is compilable standalone, by
having it include any headers its contents depend upon
and
But don't include headers that you don't need; they just create stray dependencies.
Consider this technique to help enforce header self-sufficiency: In your build, compile
each header in isolation and validate that there are no errors or warnings.
Moreover you should always include your own .h first, since this maximizes the probability of finding out if there are inclusion errors.
In all cases, headers should be swappable, so that if your file includes a.h and b.h, both possible orders should do.

difference in including header in .cpp and .h

I have a code in which I #include<linux/videodev2.h>. There are three files:
one header file- includes: stdint.h and stdlib.h. Defines a couple of functions, a struct, say abc, and some #define macros. One of the functions is
int func(int, uint32_t, size_t, abc*);
one cpp file with a lot of methods, including definition of the functions in the .h file.
one main.cpp which has main() which has a function call to the method in the .h file (complete file below). This file is only for testing purposes.
#include "head.h"
int main() {
func(5, (uint32_t)5, (size_t)5, 0);
return 0;
}
What is see is a curious case:
If I include linux/videodev2.h only in .h file, uint32_t and other things defined in this header are not accessible by the .cpp files. (erros I get are: uint32_t was not declared in this scope, and uint32_t does not name a type, among others). This happens even if the first line of the .h file is #include<linux/videodev2.h>
If I include the videodev2 header in both the cpp files, it works only if I import it (videodev2) before the .h file.
If I use func(5, (uint32_t)5, (size_t)5, (abc*)0); in the main.cpp file, I get the error that abc is not declared in this scope.
I am compiling using the command: g++ main.cpp head.cpp
I am unable to figure out why is this. I would like to include the videodev2 header in the .h file since, it is almost certain that the code using the .h file will be dependent on it. But it seems that including it in .h file has no effect at all.
I must be honest here. This was C code which I had to convert to C++. I know that I am not conforming to the best practices and standards. But why is this behaviour seen?
Remember that the #include directive indicates to the preprocessor the contents of the specified file should be treated as if they appeared directly in the source file in place of the directive (paraphrased from MSDN).
With that in mind, it seems like you are encountering improper order of #includes and also missing #includes. My guess would be that you are not including your own header file in your .cpp files. This would explain cases one and three. Consider the following files:
// header.h
// #include <linux/videodev2.h> <-- Option 1
class A {
void func(uint32_t var);
};
// header.cpp
void A::func(uint32_t var) {
// implementation
}
// main.cpp
// #include <linux/videodev2.h> <-- Option 2
#include "header.h"
// #include <linux/videodev2.h> <-- Option 3
int main() {
// implementation; something creates an instance of A and calls func
}
Now, Option 1 is not exactly desirable; it's good practice to avoid #includes in header files because they can increase build times and create unwanted dependencies. However, it will ensure that the types header.h requires are there for it to use. The essential bit is that the contents of linux/videodev2.h have to appear before the contents of header.h, anywhere that header.h is #included.
This brings me to Option 2. Option 2 will also compile correctly, because linux/videodev2.h is included before your header, and your header relies on types defined in it. Also important is that both main.cpp and header.cpp must #include "header.h", because they reference symbols declared in it.
If you were to go with Option 3, you would get compilation errors that the type uint32_t is not defined, and the compiler would point to your header file. This is because the contents of the header file appear before the contents of linux/videodev2.h, and so the compiler does not yet understand what the type uint32_t is when it encounters it.
So, given all that, you have choices: include `linux/videodev2.h' before each include of your own header file, or include it directly in your header file. I mentioned earlier that the latter is not good practice, but for your particular case, it might be the better option of the two, in case your header file needs to be included in many .cpps.
I think this would be a good opportunity to dive into precompiled headers, but I'm not as well-versed in them, so I'd leave it to someone who has more experience to explain them.
Hope this helps :)
Found the answer. There was .h.gch file in the directory. I didn't know about precompiled header. Thanks ktodisco for the insight. I still have no idea why that file was there in the first place.

Makefile 'fdopen: Bad file descriptor' error

I'm making a makefile, and getting this error:
List.h:10:18: error: calling fdopen: Bad file descriptor
I have no idea why it happens.
Here's the beginning of List.h:
#ifndef List_h__
#define List_h__
#include "Data.h"
#include "general.h"
where #include "Data.h" is the 10th line. Data and then general is the order in which the dependencies are written in the makefile:
List.o: List.cpp List.h Data.h general.h
g++ List.cpp $(f)
data doesn't include anything and general includes only iostream, and no other class also includes iostream.
Here's Data.h:
#ifndef Data_h__
#define Data_h__
class Data
{
private:
public:
//default constructor
Data() {}
//destructor
virtual ~Data()=0;
/*****************************************************************************
* function name: operator<
* The Input: This Data, other Data
* The output: The operator will compare between two datas. The comparison will
* be used to create a sorted list.
*****************************************************************************/
virtual bool operator<(const Data& other) const =0;
};
Data::~Data() {}
#endif //Data_h__
I initially had the trivial implementation of Data's destructor after the =0, and I've also tried to move the trivial implementations of the constructor and destructor to a .cpp file. All of the above didn't work. Please help - I've been stuck on this makefile for hours and it's driving me crazy! Thanks!
First, check to see if you are using precompiled headers. If so delete all the precompiled headers.
If that doesn't work, then I think this may help. There is a bug in some version of g++ with including a header multiple times in a single unit.
Look at see if you are including Data.h multiple times.
Precompiled headers: look for .gch files and delete them.
Precompiled header
Often large projects have many header files that are included in every source file. The time the compiler takes to process these header files over and over again can account for nearly all of the time required to build the project. To make builds faster, GCC allows users to `precompile' a header file; then, if builds can use the precompiled header file they will be much faster.
To create a precompiled header file, simply compile it as you would any other file, if necessary using the -x option to make the driver treat it as a C or C++ header file. You will probably want to use a tool like make to keep the precompiled header up-to-date when the headers it contains change.
A precompiled header file will be searched for when #include is seen in the compilation. As it searches for the included file (see Search Path) the compiler looks for a precompiled header in each directory just before it looks for the include file in that directory. The name searched for is the name specified in the #include with `.gch' appended. If the precompiled header file can't be used, it is ignored.
For instance, if you have #include "all.h", and you have all.h.gch in the same directory as all.h, then the precompiled header file will be used if possible, and the original header will be used otherwise.