"Undefined reference to" Error while linking object files [duplicate] - c++

This question already has an answer here:
"undefined reference to" errors when linking static C library with C++ code
(1 answer)
Closed 6 years ago.
I realize this question has been asked in a number of ways including this very comprehensive answer but I have looked at many and tried fixing my error to no avail.
I am using .cpp and .c files to create a program. I compiled all files with g++, it seemed to have no more linking errors, though it gave me a bunch of C++ errors related to the C syntax. This was the command I used:
g++ -o program main.cpp /data/*.c -l[...libs]
The main.cpp calls functions in the .c files.
I then understood that one should not try to compile both .c and .cpp files with one compiler, instead to use gcc for one, g++ for the other, and thereafter to simply link the object files.
So I did this (the .c files are part of a library, and already have .o files)
g++ -c main.cpp
g++ -o program main.o /data/*.o -l[..libs]
But then here I will get "undefined reference to" errors for functions called from main.cpp to the precompiled .c files, errors which I didn't get previously.
Could anyone help? Or do I maybe need to provide more information?
EDIT (a more in depth excerpt of code, I've tried to simplify otherwise this will be impossible to read, but let me know if I still need to add stuff, I'll try to remove unnecessary code):
main.cpp :
#include "header.h"
int main(int argc, char** argv) {
string s1 = argv[2];
fn1(s1)
}
header.h
void fn1(string s1)
mycfile.c
#include "header.h"
void fn1(string s1){
fprintf(stdout, " you entered %s", s1);
fflush(stdout);
}
ANSWER:
#Smeehey helped me figure out the solution, it was actually that I was still including the old headers in an .hpp file I was using. But the core solution was indeed to use the external C{}.

This is highly likely to do with C-vs-C++ linkage. In your main.cpp, you probably have something like this:
#include <data/header.h>
where header.h refers to your c library. Replace it as follows:
extern "C" {
#include <data/header.h>
}
This tells your c++ compiler not to use c++-style name mangling when defining the required symbols from the header, allowing the linker to successfully find them in the c-compiled .o files.

You have to compile C files with the gcc command, C++ files with either gcc or g++, and link with the g++ command. This sequence will probably work:
gcc -c data/*.c main.cpp
g++ -o program *.o -l <libs...>
Next step: learn to write proper makefiles.

This is a shot in the dark but the problem might be the way C and
Cpp files are compiled is simillar yet slightly different....
Due to name spaces the function foo would generate the symbol some_prefix#foo
Unlike C whereas goo generates the symbol goo
Try doing the following in your .cpp files
extern "C"
{
#include "yourcfilesheader.h"
}
And please attach your code

Related

How does C++ linker know what .cpp files to use

I am a C++ learner and I came across a concept of separating code into multiple files to speed up compiling process on bigger projects.
However what the book doesn't tell me and I have tried to find it in other books and on the web, but with no luck is how does linker (during compilation) knows what files to include.
When I make new file I connect its header to the main file with #include "newfile.h", however in this header I don't write where to find definitions of functions.
So how I imagine the process is that it starts in the main file and there it finds "connections" to other files. The question is how it finds those .cpp files that as far as I see don't need to be named the same as its header file.
Exmple:
Main file:
#include <iostream>
#include "krneki_H.h"
using namespace std;
int main()
{
krneki1();
krneki2();
krneki3();
}
And header file:
void krneki1();
void krneki2();
void krneki3();
And new .cpp file:
#include <iostream>
#include "krneki_H.h"
using namespace std;
void krneki1() {
cout<<"Krneki1"<<endl;}
void krneki2() {
cout<<"Krneki2"<<endl;}
void krneki3() {
cout<<"Krneki3"<<endl;}
Notice that there is no indication to use second cpp file. It just knows to use it. Does it search all .cpp files in the map?
Thank you for answer.
You compile both .cpp files using gcc -c or a similar command line, and then pass both of the .o files produced to the linker. The linker does not magically figure out that you want to compile another .cpp file.
For example
gcc -c main.cpp -o main.o # compile
gcc -c krneki_H.cpp -o krneki_H.o # compile
gcc main.o krneki_H.o -o main # link
Your IDE may take care of these details automatically, in which case it compiles all .cpp files you added to your project, then links all the .o files produced by the compilation step.
No. It doesn't just know to use it. In your example, if you compile with main.cpp and without that new cpp file, you'll get an "undefined reference" error.
What happens is that you're using a fancy IDE that automatically compiles all cpp files. It includes them all by default in your makefile.
I recommend that you try to design a makefile from scratch, and see for yourself how you'll get that "undefined reference" error if you don't include the cpp file that has the implementations of your functions.

Undefined reference / multiple definition errors with GCC [duplicate]

This question already has answers here:
One definition rule in c++
(4 answers)
Closed 7 years ago.
I'm a newcomer to C++. I'm having trouble building a simple multi-file project with g++. Here are my files:
something.h
class Something
{
public:
void do_something() const;
} thing;
something.cpp
#include <iostream>
#include "something.h"
void Something::do_something() const
{
std::cout << "Hello!" << std::endl;
}
main.cpp
#include "something.h"
int main()
{
thing.do_something();
}
Here is what I tried:
g++ main.cpp gives an error that do_something is an undefined reference, which makes sense because the compiler has no idea something.cpp has anything to do with something.h.
g++ main.cpp something.cpp: there are 'multiple definitions' of thing, even though I clearly defined it only once.
g++ -c main.cpp something.cpp: no errors! However, when I try running g++ *.o it gives me the same error as above, so I'm thinking this is a linker error.
Can anyone explain how to compile a multi-file project, and why my approach isn't working? I'm pretty confused right now because above is what most of the C++ examples on Stack Overflow look like.
Sidenotes:
I did try the suggestions here, but they didn't address linking issues with headers specifically.
I'm not trying to redefine thing in main; if I wanted to do that, I would have typed up Something thing.
g++ main.cpp gives an error that do_something is an undefined reference, which makes sense because the compiler has no idea something.cpp [...]
... which contains the definition of the member function do_something exists. So you reference an undefined function.
g++ -c main.cpp something.cpp: no errors! [...]
... since you're only compiling the files, not linking them together.
When you link them together, you end up with
[...] 'multiple definitions' of thing [...]
which is exactly what you're doing:
class Something {
// content
} thing;
is the same as
class Something {
// content
};
Something thing;
And since #include "something.h" works by effectively copying the contents of the included file right into the including file, you end up with 2 files with a line
Something thing;
in each of them. And this is what the linker (called from the compiler frontend) is telling you: There are multiple definitions of the global variable thing.
To solve this: Don't put definitions for global variables into header files, only declarations:
extern Something thing;
And then add a definition in a single source file:
Something thing;
Or, better, try to avoid global variables.
One more thing: If you aren't doing it already, use include guards for your headers.
make sure you have added all files to the project.
Like if you are using IDE e.g, DEV C++ you have to add each .cpp or .h file to the project.

Confused about C++ #include

My project has this folder structure:
Project/
--Classes/
----Class1.h
----Class1.cpp
--main.cpp
"Class1.h" contains method definitions, "Class1.cpp" is the source code for "Class1.h".
The source code of "Class1.h" is like this:
class Class1 {
public:
void do_something();
};
The source code of "Class1.cpp" is like this:
#include "Class1.h"
void Class1::do_something() {
//
}
The source code of "main.cpp" is like this:
#include "Classes/Class1.h"
int main(int argc,char** args) {
Class1* var = new Class1();
var->do_something();
return 0;
}
However, when compiling "main.cpp", the compiler doesn't know where the implementation of methods in Class1 is, so it shows linking error about undefined reference.
Do I have to add any path into the command line so the compiler knows what source files it has to compile? How to tell the compiler that it must compile "Class1.cpp" also?
You need to feed all files in your project to the compiler, not just "main.cpp". Here you can read about the basics of compiling multiply files together with Gcc.
Another option would be to compile your classes as a dynamic or static library, but you should start with simply compiling them together if you're not quite familiar with libraries.
You need to know about building (compiling and linking) C++ applications. This topic usually don't describe in programming books about C++ and only way to do it - google and programming community sites with articles.
Fast answer is:
g++ -c Classes/Class1.cpp -o Class1.o
g++ -c main.cpp -o main.o
g++ Class1.0 main.0 -o ProjectName
It's a simple set of commands to compiling and linking program. Usually it would be done by build system (make, qmake, cmake, waf, scons, ant etc). Also, IDE can build program without additional configuration, Visual Studio for example.
The correct way to do it is doing the header inclusion in the Class1.cpp file. That way if the Class1.cpp is compiled as a library, you can use the header file to get the declarations.
The other way around, if you will directly use the Class1.cpp, compiling it with your project. You should include Class1.cpp in your main.cpp.

C++ Header and CPP includes

quick question.
I am trying to get C++ nailed down, and today I spent hours with a double definition linker error("this has already been defined!") and I finally realised it's because I had the layout as such:
main.cpp
#include Dog.cpp
Dog.cpp
#include Dog.h
Dog.h
// (Dog class and prototype of test function)
And now that I've cleared that up by including the Dog.h instead of the Dog.cpp in the main.cpp.
By including the .h file, does the .cpp file with the identical prefix get compiled with the program?
I was astounded when the program ran with only the .h included and no references whatsoever to Dog.cpp. I spent ages Googling but no answers really helped me understand what was going on.
Edit: I forgot to add that I prototyped in the .h, and defined the function for the class in the .cpp and that's what gave me the "already defined" error.
By including the .h file, does the .cpp file with the identical prefix get compiled with the program? I was astounded when the program ran with only the .h included and no references whatsoever to Dog.cpp.
No.
Your program is built in phases.
For the compilation phase, only declarations are needed in each translation unit (roughly equivalent to a single .cpp file with #includes resolved). The reason that declarations even exist in the first place is as a kind of "promise" that the full function definition will be found later.
g++ -c Dog.cpp # produces `Dog.o`
g++ -c main.cpp # produces `main.o`
For the linking phase, symbols are resolved between translation units. You must be linking together the result of compiling Dog.cpp and of compiling main.cpp (perhaps your IDE is doing this for you?), and this link process finds all the correct function definitions between them to produce the final executable.
g++ Dog.o main.o -o program # produces executable `program`
(Either that, or you actually haven't got to the link phase yet, and merely have an object file (Dog.o); you can't execute it, partially because it doesn't have all the function definitions in.)
The two phases can be done at the same time, with the "shorthand":
g++ Dog.cpp main.cpp -o program # compiles, links and produces executable
No, the .cpp file does NOT automatically get compiled. You can either do that manually, create a makefile, or use an IDE that has both of them in the same project.
You don't specify how you are compiling it. If you are using an IDE and have a new .h and .cpp to the project automatically then it will all be compiled and linked automatically.
There are 2 stages to making an executable to run: compiling and linking. Compiling is where the code gets interpretted and translated into lower level code. Linking is where all of the functions that you used get resolved. This is where you got the duplicate function error.
Inclusion does not automatically cause compilation, no.
In fact, the actual compiler never sees the #include statement at all. It's removed by an earlier step (called the preprocessor).
I'm not sure how it could build if you never compiled the Dog.cpp file. Did you reference any objects with code defined in that file?

Understanding C++ Compilation

I have recently become aware that I have no idea, genericly speaking, how a c/c++ compiler works. I will admit this initialy came from trying to understand header guards but came to the realization that I am lacking in how compiling works.
Take Visual C++ for instance; Theres the "Header Files" folder, the "Resources Files" folder, and "Source Files" folder. Is there any significance to the separation of these folders and what you put in them? To me, they are all source files. Take the code snippets:
Snippet 1
//a1.h
int r=4;
and
//a1.cpp
int b //<--semicolon left out on purpose
and
//main.cpp
#include <iostream>
#include "a1.h"
void main()
{
cout << r;
}
The compiler errors out saying "a1.cpp(3) : fatal error C1004: unexpected end-of-file found" where I would expect it wouldn't because the a1.cpp file is not #included where the main method exists where in the next code snippet
Snippet 2
//a1.h
int r=4 //<--semicolon left out on purpose
and
//a1.cpp
int b = 4;
and
//main.cpp
#include <iostream>
void main()
{
cout << b;
}
Errors out because "main.cpp(6) : error C2065: 'b' : undeclared identifier". If you include the a1.cpp like so
Snippet 3
//a1.h
int r=4 //<--semicolon left out on purpose
and
//a1.cpp
int b = 4;
and
//main.cpp
#include <iostream>
#include "a1.cpp"
void main()
{
cout << b;
}
the compiler complains "a1.obj : error LNK2005: "int b" (?b##3HA) already defined in main.obj". Both snippets 2 and 3 ignore the fact that int r = 4 does not have a semicolon missing as I suspect that it has something to do with its a xxxx.h file. If I remove the a1.cpp file from the project on snippet 1, then it compiles fine. Clearly what I have expected is not what I am getting. Theres plenty of books and tutorials on how to code in cpp, but not much in the way cpp handles files and source code in the complition process. What on earth is going on here?
Your questions aren't really about the compiler, but about how your IDE is handling the entire build system. The build systems for most C/C++ projects compile each .c or .cpp file separately, and then link the resulting object files together into a final executable. In your case, your IDE is compiling any file you have in the project with a filename extension of .cpp and then linking the resulting objects. The behaviour you're seeing can be explained as follows:
a1.cpp is missing a ;, so when the IDE tries to compile that file, you get the error about 'unexpected end of file'.
b isn't declared anywhere in the main.cpp compilation unit, so you get an error about an undefined identifier.
b exists in both the main.cpp and a1.cpp compilation units (obviously in a1.cpp, and via your #include for main.cpp). Your IDE compiles both of those files - now a1.o and main.o each contain an object called b. When linking, you get a duplicate symbol error.
The important point to take away here, which explains all of the behaviour you see, is that your IDE compiles every .cpp file - not just main.cpp and the files it includes - and then links the resulting objects.
I recommend setting up a command-line test project with a makefile you create yourself - that will teach you all about the inner workings of build systems, and you can then apply that knowledge to the inner workings of your IDE.
header files are not compiled
an #include directive literally pastes the contents of the includable file instead of the #include line
All source files (redargless of main) are compiled into .o or .obj files.
All obj files are linked together along with external .lib files if there are any
You get an executable.
Regarding point 2:
example
//a.h
int
//b.h
x =
//c.h
5
//main.cpp
#include <iostream>
int main()
{
#include "a.h"
#include "b.h"
#include "c.h"
;
std::cout << x << std::endl; //prints 5 :)
}
This isn't a full answer, but hth, my2c, etc :)
Since it seems that there are two ways of understanding your question, I will answer to the understanding C++ compilation part.
I suggest that you start by reading the "compiler" definition in Wikipedia. After that, try Google search for compiler tutorials to build up your comprenhension about compilers. More specific to C++, you can read about #include and preprocessor directives (try Google search for those terms.)
If you still want to understand compilers further, I suggest a compiler book. You'll find a good list of books on StackOverflow.
The #include statement inserts that file into the file making the #include. Your snippet 3 main.cpp thus becomes the following before compilation.
// main.cpp
// All sorts of stuff from iostream
//a1.cpp
int b = 4;
void main()
{
cout << b;
}
The reason you are getting a linker error is that you are defining b twice. It is defined in a.cpp and in main.cpp.
You may wish to read about declaring and defining.
You tell the build system what files to compile. In the case of Visual C++, it will automatically compile any file named "*.cpp" that you add to the project. Though you can go into the project settings and tell it not to.
It will not compile files named *.h (though it can if you explicity tell it to.
The #include directive, is something the compiler processes before it does any compilation (it's called the pre-processor). It basically takes the file that it is pointing it to and sticks it in the source file being compiled at the point the #include directive appears in the file. The compiler then compiles that whole thing as one complete unit.
So, in your example cases:
Snippet 1
Bote a1.cpp and main.cpp are compiled seperately by the build system. SO, when it encounters the error om a1.cpp, it reports it.
Snippet 2
Note that it compiles these files seperately, with no knowledge of each other, so when your reference b in main.cpp, it does not know that b is defined in a1.cpp.
Snippet 3
Now you've included a1.cpp in main.cpp, so it compiles main.cpp, sees a definition for b and says, OK I have a b at global scope. Then it compiles a1.cpp, and says OK, I have a b at global scope.
Now the linker steps in and =tries to put a1 and main together, it;'s now telling you, hey I have 2 b's ate global scope. No good.
The compiler picks up source files from where you tell it to. In the case of Visual C++ there's an IDE telling the compiler what to do, and the different folders are there because that's how the IDE organises the files.
Also, the error in snippet 2 is from the linker, not from the compiler.
The compiler has compiled main.cpp and a1.cpp into object files main.obj and a1.obj and then the linker is trying to make an executable combining these object files, but the variable b is in both a1.obj (directly) and main.obj (via the include of a1.cpp), so you get the "already defined" error.
The problems you see in case 1 and 3 are VS specific. VS apparently tries to compile both main.cpp and a1.cpp.
Case 1: As VS tries to compile a1.cpp, which has an syntax error (the missing semicolon), the compilation fails.
Case 2: You have not declared the variable b in your main.cpp or in any included files. Thus the compilation fails.
Case 3: This is a linker error. Due to the include, int b has been declared in main.cpp as well as in a1.cpp. Since none of them is either static or extern, two global variables with the same identifier have been declared in the same scope. This is no allowed.