Class issue with main C++ - c++

I created my header file for a class and #included "theclassname.h" in main.cpp but when I try to compile I get "undefined reference to "ClassName::TheConstructor(bool, int*, std::basic_string, std::allocator >)""
I coded the constructor and a function called "ClassName::start" inside of my Classname.cpp file but for some reason it is giving this undefined reference issue for this start function and for my destructor which is also coded in my cpp file. Every call I make in main to a function that was coded inside of the header file doesn't trigger this error but every call made to a function coded in my .cpp file triggers this.
I've seen a lot of posts about this but I've coded them properly with the correct parameters and return types and made sure the function name was the same as the one defined in the header file. What else could be causing this besides misspelling something because I've checked for that over 10 times.
Thanks
#ifndef THECLASSNAME_H
#define THECLASSNAME_H
#include <iostream>
class TheClassName {
public:
TheClassName(bool theBool=true, int *theArray=0,
std::string message="-1");
~TheClassName();
void start();
void setBool(bool theBool) {aBool=theBool;}
bool getBool() {return aBool;}
void setMessage(std::string message) {mssg=message;}
std::string getMessage() {return mssg;}
std::string getHello() {return hello;}
private:
int *anArray;
bool aBool;
std::string mssg;
std::string hello;
void aFunction1(bool);
void aFunction2();
void aFunction3();
void aFunction4();
};
#endif
Sorry Everyone just fixed it! In my makefile I did
exec1: main.o classname.o
g++ -o exec1 main.o
Instead of
exec1: main.o classname.o
g++ -o exec1 main.o classname.o
Thank you guys so much!

That sounds like you're getting the error at the linker phase. Are you also compiling the file that you have the C++ class definition in and not just including the header file? You need to have a separate C++ file with the function definitions for you class, compile this file as well and include the object file in the linker command line so you don't get your undefined reference errors when you link the final executable.

Please post your code and also post the build command and output, if possible.
This is a linkage rather than compilation problem and it sounds like the compilation unit containing your constructor and destructor declarations have not been linked into the executable - in other words, the linker can't find your functions.

Related

g++ fails to link .o files into an executable

I am doing an example drill in the textbook I am using to learn from. All I need to do is compile, link and run the following 3 files:
//file my.h
extern int foo;
void print_foo();
void print(int);
my.h is a simple header file that declares the two functions and a 'global' int foo, with no initial value.
//file my.cpp
#include "my.h"
#include "std_lib_facilities.h" //not included but not source of error
void print_foo()
{
cout << foo << endl;
}
void print(int i)
{
cout << i << endl;
}
my.cpp contains the implementation of the functions included from my.h. std_lib_facilities.h is a file from the textbook, and is not the source of error (according to g++). I can edit it into the body of the question if needed.
//file use.cpp
#include "my.h"
#include <iostream>
int main() {
foo = 7;
print_foo();
print(99)
char cc; cin >> cc;
return 0;
}
use.cpp serves as the main implementation file in this program, and tries to use all three declared & defined objects.
I took the two step command approach to build using g++. First, I compiled both .cpp files:
g++ -c my.cpp use.cpp
which created two object files, my.o and use.o. I used the following command to link them:
g++ -o myprog my.o use.o
giving me this error:
Undefined symbols for architecture x86_64:
"_foo", referenced from:
print_foo() in my.o
_main in use.o
(maybe you meant: __Z9print_foov)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have tried putting
int foo;
into my.h instead of
extern int foo;
which gave me the same error.
I have tried using the
-std=c++11
flag as well which resulted in the same error.
I am using a MacBook Pro with the latest macOS (just updated in fact), if that helps with interpreting the error message.
I have tried to initialize foo, which didn't change anything.
In addition, I have tried updating the command line tools, same error.
From what I understand, the error is telling me that, even though my.h is included in both files, neither one can actually implement any function using the foo variable (which it calls _foo), despite it being explicitly declared in my.h. My guess is that the linker is using the wrong names under the hood, which make it impossible to link into an executable. This comes from the fact that the error mentioned a
__Z9print_foov
which exists nowhere in any of the files.
It almost seems like a g++ or macOS/Command Line Tools bug at this point. I don't want to add the declarations each time, because that creates duplicate symbol errors anyway. Putting my.cpp and use.cpp into one file would probably link properly, but I need to make sure that I can actually link multiple cpp files, because I will eventually (hopefully) be working with multiple cpp files that need to be linked. Any help is appreciated!
Here you declare a variable:
extern int foo;
and you use the variable:
cout << foo << endl;
but you did not define the variable anywhere. The linker error says that the linker could not find the variable's definition. To fix this, put int foo; at file scope in one of the .cpp files.
In the question you say that changing extern int foo; to int foo; gives the same error. However if you look more carefully at the error message I think you will find that it gives a different one, about multiple definitions.
I suggest to compile in two commands g++ -Wall -c my.cpp (that gives a my.o) and g++ -Wall -c use.cpp (giving use.o), then link a program with g++ my.o use.o -o myprog. Actually you should write a Makefile (see this for inspiration) and simply run make
Your translation units my.cpp and use.cpp are both declaring some extern int foo; variable which is never defined. So you need to define it in one single file (but not in others!), probably by adding (into my.cpp alone for example)
int foo;
(without the extern) or even with some explicit initial value e.g. int foo = 34;
This comes from the fact that the error mentioned a __Z9print_foov which exists nowhere
It is a mangled name, which is referenced (but not defined) in both object files (see also this).
It almost seems like a g++ or macOS/Command Line Tools bug at this point
You are very unlikely to find bugs in compiler tools (both GCC & Clang/LLVM are extremely well tested; since they are multi-million lines free software, they do have residual bugs, but you have more chances to win at the lottery than to be affected by a compiler bug). I'm coding since 1974, and it happened to me only once in my lifetime. A more realistic attitude is to be more humble, and question your own code (and knowledge) before suspecting the compiler or build chain.
BTW, always compile first with all warnings and debug info (e.g. g++ -Wall -g and perhaps also -Wextra). Use the gdb debugger. When you are convinced that your code has no bugs, you might benchmark it by asking the compiler to optimize (so use g++ -Wall -O2 perhaps also with -g to compile).
Read also the linker wikipage. Dive into your C++ textbook (see also this site and the C++11 standard, e.g. n3337 draft) to understand the difference between declaring and defining some variable or function. You generally declare a global extern variable in some common header (included in several translation units), and define it once somewhere else, but the good practice is to avoid having lots of global variables. See also C++17 new inline variables.

Undefined reference error when using a simple class inside my function

I am getting nuts with this error so I thought some of more experienced developers can help me in this regard.
I am trying to compile a sample project which uses a C++ library (named Poco). My project is linked to compiled poco libraries.
Below is my (most simplified) code:
#include "Poco/UUID.h"
class x
{
void func1()
{
new Poco::UUID(); //A
}
};
void func1()
{
new Poco::UUID(); //B
}
Now when above code is compiled, line 'A' has no error but for line 'B' linker says:
undefined reference to `Poco::UUID::UUID()'
What is the reason? When I instantiate a class from external lib in a class method no error occurs but the same code in a function produces linker error? (When I comment line B, no error occurs and linker output files are generated)
My configuration: Win7/g++/CodeLite/MinGW-4.7.1
*Update 2:*Thanks. My problem is now resolved and the issue is that I had compiled library using MSVC compiler while my application was being compiled using g++ (both under Windows platform). So I re-compiled library using g++ and everything works fine now.
Update 1: here is my IDE's output when I build my project:
C:\Windows\system32\cmd.exe /c "mingw32-make.exe -j 4 -e -f "dll1.mk" all"
----------Building project:[ dll1 - Debug ]----------
g++ -shared -fPIC -o ./Debug/dll1.so #"dll1.txt" -L. -Lc:/poco/lib -lPocoFoundationd
./Debug/PluginLibrary.o: In function `Z5func1v':
C:/Users/PARS/Documents/codelite/workspace1/dll1/PluginLibrary.cpp:12: undefined reference to `Poco::UUID::UUID()'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [Debug/dll1.so] Error 1
dll1.mk:77: recipe for target `Debug/dll1.so' failed
1 errors, 0 warnings
Your member function x::func1() is never ODR-used in that compilation unit (source file). Most compilers only generate compiled code for a member function defined inside the class definition if that member function is ODR-used within the compilation unit that is being compiled. Suppose some other source file does use x::func1(). If you compile that other source file, the compiler will produce object code for x::func1() in the object file that corresponds to that other source file.
The compiler can get away with bypassing the process of generating compiled code for x::func1() here because the class definition has to be the same across all compilation units. If you compile some other source file that has a different definition of class x you have violated the one definition rule. This is undefined behavior and no diagnosis is required.
If no source file uses x::func1() you have some dead code that just never happens to be compiled. The code has an error but it's never detected.
The compiler cannot get away with bypassing generating compiled code for the free function func1(). This function has external linkage; there's no way the compiler can tell if it might be used somewhere else. The compiler must generate compiled code for that free function.
Here's a minimum working example:
class Missing {
public:
Missing();
int value;
};
class UsesMissing {
public:
int use_missing () {
Missing missing;
return missing.value;
}
int dont_use_missing () {
return 0;
}
};
#ifdef DEFINE_USE_MISSING
int use_missing () {
Missing missing;
return missing.value;
}
#endif
int main () {
UsesMissing test;
#ifdef USE_MISSING
return test.use_missing();
#else
return test.dont_use_missing();
#endif
}
Compile with neither DEFINE_USE_MISSING or USE_MISSING defined and this compiles and links just fine with g++ and clang++. Define either one of those flags and the file fails in the link step because of the undefined reference Missing::Missing().
You should link with the correct library to fix your link (see Poco docu for the correct one).
func1 has extern linkage and so linker need Poco::UUID
whereas X::func1 is inline/private/unused.
if you use static foo1() or inline foo1() the linker error disappears
if you use x::func1 or implement x::func1 outside of the class x{}; the error linker appears

Linking with a library from external directory

Edit: I have updated my question with changes I've made, upon answers.
I'm trying to link to a little library that I've wrote to learn ho this is done with C++ with no luck. G++ is complaining with undefined reference.
The root directory of library I want to link is in directory ~/code/gklib/cxx/. The structure of this directory is as follows:
~/code/gklib/cxx/
|
|`-> gk.{hh,cc}
|`-> libgk.o
|
`-> lib/
|
`-> libgk.a
I have compiled gk.cc with -c flag, then transformed the resulting object file to a .a file with ar rvsc lib/libgk.a libgk.o.
The client to this library is at folder ~/code/cpp. In this directory I compiled some_stuff.cc to an object file again, then I tried to link to it with this command:
$ cxx some_stuff.o -L../gklib/cxx/lib -lgk -o some_stuff
I get this error:
some_stuff.o: In function `main':
some_stuff.cc:(.text+0x49): undefined reference to `void GK::algorithms::insertionSort<int, 5ul>(int*)'
collect2: error: ld returned 1 exit status
These are contents of these files:
~/code/cpp/some_stuff.cc
#include <cstdlib>
#include <iostream>
#include <gk.hh>
using namespace std;
int main(int argc, char **argv) {
int i = -1;
int arr[5] = { 3, 4, 2, 1, 5 };
const size_t len = sizeof(arr)/sizeof(int);
GK::algorithms::insertionSort<int, len>(arr);
while(++i < 5)
cout << arr[i] << " ";
cout << endl;
exit(EXIT_SUCCESS);
}
~/code/gklib/cxx/gk.cc
#include "gk.hh"
template<class T, size_t len>
void GK::algorithms::insertionSort(T arr[len]){
// insertion sort
}
~/code/gklib/cxx/gk.hh
#pragma once
#include <cstdlib>
#define NAMESPACE(ns) namespace ns {
#define END_NAMESPACE(ns) }
NAMESPACE(GK)
NAMESPACE(algorithms)
template<class T, size_t len>
extern void insertionSort(T arr[len]);
END_NAMESPACE(algorithms)
END_NAMESPACE(GK)
I've tried many variations on my commands with no result. Internet is full of tutorials and forums with instructions those did not work for me. This code ran perfectly when all the stuff was in one file. How can I resolve this problem? Thanks in advance.
I think it's more something like:
cxx some_stuff.o -L$HOME/gklib/cxx/lib -B../gklib/cxx/lib -lgklib -o some_stuff
-lgklib, not -Igklib (-I option specify an include folder)
but you'll have to rename your gklib.a by libgklib.a
Maybe you can even remove -B../gklib/cxx/lib, just try it out :)
I see several problems: in order:
If this is your exact command line, the -L option doesn't
point to the structure you've shown above (where there is no
cxx in the path).
I don't know why you're using -B. This tells the compiler
where to look for its libraries, etc. Normally, this is only
necessary when you want to test parts of the compiler you've
modified.
I don't see where you've specified to link against the
library. Since the library doesn't respect the usual naming
conventions (libname.a), you'll have to
specify it directly (in the same way you'd specify an object
file), and the -L option isn't used. Alternatively, you name
it libgk.a, or something like that, and add a -lgk to the
command line, after your object files.
Finally, the error messages refer to an instantiation of
a template. This typically occurs because the implementation of
the template is in a source file, not in the header. The
standard requires that the implementation be visible when it
triggers the instantiation of a template. The way g++ (and
almost every other compiler) works is that if the implementation
isn't visible, they suppose that the template will be
instantiated in another translation unit, and output external
references to it. But if the implementation is in a source,
there will be no instantiation, and you'll get a linker error.
(You'll also not find the assembler for the instantiation
anywhere, either, because the template hasn't been
instantiated.) You should include the source code at the bottom
of your header, and not compile it separately.
I have solved this problem, with the help of this and this questions. The problem lies in the fact that void insertionSort(T *) is a template function, and template functions can only be implemented in header files. The reason for this is, the compiler needs to reach the definition of the to create a new function for each call to it with a different type as the argument to template. I have moved the definition of this function to gk.h, which resulted in a successfull compilation and linkage.

File inclusion errors (C++): undefined reference to ______

Whenever I compile something that #includes a user-defined class, I get these compilation errors that always look like: main.cpp: undefined reference to Complex::Complex(double, double)
I've reduced the problem to a set of three extremely bare files: main.cpp, and for example, Complex.h and Complex.cpp. I still get undefined reference errors. I'm developing in Code::Blocks on Windows but I get the same thing using g++ in Ubuntu. Why does this happen? I've tried building Complex.cpp before main.cpp in Code::Blocks, and I've tried g++ main.cpp Complex.cpp as much as I've tried just g++ main.cpp. Same errors every time.
/*======== main.cpp ========*/
#include "Complex.h"
int main()
{
Complex A(1.0, 1.0);
return 0;
}
/*======== Complex.h ========*/
#ifndef _COMPLEX_H
#define _COMPLEX_H
class Complex
{
public:
double x, y;
Complex(double real, double imag);
};
#endif
/*======== Complex.cpp ========*/
#include "Complex.h"
Complex::Complex(double real, double imag)
{
x = real;
y = imag;
}
ed: now I get different errors so I must be doing something completely wrong. Using the same code as above, I get:
main.cpp: in function 'int main()':
main.cpp:5:5: error: 'Complex' was not declared in this scope
main.cpp:5:13: error: expected ';' before 'A'
This is bizarre. Everything worked earlier when I had the class in a .cpp file, but that's "bad practice" so I moved my class definitions into .h files and kept the implementation in .cpp files, and now nothing works.
That's not a compilation error, it's a link error. You need to make sure to link all of your objects together. You can do that in a couple ways:
g++ main.cpp Complex.cpp
Should work fine (and does here when I tried with your example). You can also do it in steps:
g++ -c main.cpp
g++ -c Complex.cpp
g++ main.o Complex.o
While we are left in the dark whether this is the actual code (probably not as it works for several others), let's comment on the code itself a bit... (this won't have any effect on the linker error)
Names starting with an underscore followed by a capital letter, e.g. _COMPLEX_H, are reserved for the implementation of the C++ compiler and the C++ standard library. Don't use them.
Member variables are best made private. There is rarely any need to make actual data member public (sometimes it is reasonable to make non-function members public, e.g. an event class where users can subscribe callbacks, but these typically behave like functions although they are technically objects).
Initialization is best done in the member initializer list. That is, the constructor would look something like this:
Complex::Complex(double real, double image):
x(real),
y(imag)
{
}
Finally, to venture a few guesses what is going wrong with the actual code to cause the linking problem:
The constructor is defined to be inline. Obviously, this won't work unless the definition is visible where the constructor is used.
The declaration of Complex somehow made it into an unnamed namespace and thus the definition happens to define a different class than the one seen by main.cpp.

Undefined reference linking error when using &MyClass::MyFunction

this just has me stumped, so I thought I'd query here:
I have a class as follows:
class MyClass {
public:
void myThreadFunc();
};
That's in the header. In the constructor
MyClass::MyClass() {
...
boost::thread t(boost::bind(&MyClass::myThreadFunc, this));
...
}
As I've seen done. There are NO compile time errors. However, when I link as follows:
g++ -o test.exe main.o MyClass.o /*specify boost and other libraries */
I get:
MyClass.o:MyClass.cpp:(.text+0xa4): undefined reference to `MyClass::myThreadFunc()'
collect2: ld returned 1 exit status
Which doesn't make any sense. What strikes me especially odd is that's its a linker error. I included both of my object files.
Can anyone tell me what's going on? If it might be relevant, I'm on MinGW on Windows.
EDIT:
Epic fail. I forgot the MyClass:: prefix when defining the function in my cpp file. I just didn't decide to check that. Almost as bad as forgetting a semicolin after a class definition.
You need to write a function body for MyClass::myThreadFunc() somewhere. Writing a constructor for MyClass is different from implementing the MyClass::myThreadFunc() member function.
If you call a function in C/C++, it must have a function body somewhere. That's why it's a linker error; it's trying to find the function body in all of the available object files, but you didn't write one so it can't.