undefined reference to; class public function not accessible at link time - c++

I'm trying to build a simple program where I defined a class and included it's header in Main. While linking, Linker complains about accessing any of the member function from class:
: undefined reference to voxel::anyFunction
even though functions are public and headers are included.
Originally I discovered the problem when creating an object of voxel - I had overloaded the default constructor, but I figure out the problem is present for any function from voxel class.
Here are some code excerpts:
voxel.hpp
class voxel
{
public:
//here defined some member variables
//ommited the constructor
void fillMemberValuesWithDummy();//sets all members to some dummy value
};
voxel.cpp
#include "voxel.hpp"
void voxel::fillMemberValuesWithDummy()
{
//does the assignment to member variables
}
Main.cpp
#include <iostream>
#include <fstream>
using namespace std;
#include "voxel.hpp"
{
voxel someVoxel;
somevoxel.fillMemberValuesWithDummy();
}
I figure it is something very stupid I am (not) doing here, but can you tell me what?

You need to link all object files to get the executable. When you have just your two source files you can compile them directly:
g++ -o myprog.exe Main.cpp voxel.cpp
When you want to divide compile and link and do it this way:
g++ -c -o Main.o Main.cpp
g++ -c -o voxel.o voxel.cpp
g++ -o myprog.exe Main.o voxel.o
Feel free to create an appropriate Makefile that generates such commands.
Remove the .exe if you OS doesn't need it.

Related

undefined reference error for static class member when it is defined in .cpp file

This question may seem similar to other "undefined reference error when accessing static class member" questions. I have explored them and what I understood is I need to define the static class member separately in a source file, so that an object is created for the static class member that holds data.
My problem is that I am following definition rules but still get the undefined reference errors.
problem can be reproduced using this code:
main.cpp
#include <iostream>
#include "src/a.hpp"
int main() {
std::cout << a::x;
return 0;
}
src/a.hpp
class a {
public:
static int x;
};
src/a.cpp
#include "a.hpp"
int a::x = 20;
I compile main.cpp using g++ main.cpp -o main. I have a test directory that has main.cpp and a sub directory src, src contains a.hpp and a.cpp.
The error resolves if i define the static variable within the header file, but other posts suggest it should lead to linker errors.
The problem was in the compile command I used, g++ main.cpp -o main does not compile src/a.cpp. Compile it with g++ main.cpp src/a.cpp -o main and it works fine.

Singleton across compilation units: linking library vs linking objects

I apologize if the title is not fully self-explanatory. I'm trying to understand why my singleton factory pattern is not working properly, and I ran into a bizarre difference when using library vs linking single objects files.
Here's a simplified version of the code:
main.cpp
#include <iostream>
#include "bar.hpp"
int main (int /*argc*/, char** /*argv*/)
{
A::get().print();
return 0;
}
bar.hpp
#ifndef BAR_HPP
#define BAR_HPP
#include <iostream>
class A
{
public:
static A& get ()
{
static A a;
return a;
}
bool set(const int i)
{
m_i = i;
print();
return true;
}
void print ()
{
std::cout << "print: " << m_i << "\n";
}
private:
int m_i;
A () : m_i(0) {}
};
#endif // BAR_HPP
baz.hpp
#ifndef BAZ_HPP
#define BAZ_HPP
#include "bar.hpp"
namespace
{
static bool check = A::get().set(2);
}
#endif // BAZ_HPP
baz.cpp
#include "baz.hpp"
Now, I build my "project" in two ways:
Makefile:
all:
g++ -std=c++11 -c baz.cpp
g++ -std=c++11 -o test main.cpp baz.o
lib:
g++ -std=c++11 -c baz.cpp
ar rvs mylib.a baz.o
g++ -std=c++11 -o test main.cpp mylib.a
Here are the outputs I get:
$ make all
$ ./test
print: 2
print: 2
$ make lib
$ ./test
print: 0
In the first case the call to A::get().set(2) in baz.hpp takes place, and the same instantiation of A is then used in the main function, which therefore prints 2. In the second case, the call to A::get().set(2) in baz.hpp never takes place, and in the main function the value set by the constructor (that is, 0) is printed.
So finally I can ask my question: why is the behavior different in the two cases? I would expect that either both print 0 once or print 2 twice. I always assumed that a library was just a compact way to ship object files, and that the behavior of linking mylib.a should be the same as that of linking baz.o directly. Why isn't that the case?
Edit: the reason, as explained by Richard, is that no symbols defined in baz.cpp are required in main.cpp, so baz.o is not extracted from the library and linked. This raises another question: is there a workaround to ensure that the instruction A::get().set(2) is executed? I would like to avoid making the singleton a global object, but I'm not sure it's possible. I would also like to avoid to include baz.hpp in the main, since there may be many bazxyz.hpp and that would require main.cpp to know in advance all of them, defying the whole purpose of the factory-like registration process...
If this is to be a static library, then some module somewhere is going to have to address something in each implementation file of the objects that are going to register themselves with the factory.
A reasonable place for this would be in bar.cpp (which is a file you don't yet have). It would contain some or all of the implementation of A plus some means of calling the registration functions the widgets you're going to create.
Self-discovery only works if the object files are linked into the executable. This gives the c++ startup sequence a chance to know about and construct all objects with global linkage.

Segment fault occurs depend on cpp sequence in gcc compile command?

I write a simple program that adds a value into a global set container when a new class (eg: One,Two) is defined:
GlobalSet.h
#include <set>
struct GlobalSet{
public:
static void* addValue(int val);
private:
static std::set<int> s;
};
GlobalSet.cpp
#include "GlobalSet.cpp"
std::set<int> GlobalSet::s;
void* GlobalSet::addValue(int val){
s.insert(val);
return NULL;
}
One.h
struct One{};
One.cpp
#include "One.h"
#include "GlobalSet.h"
void* globalset =GlobalSet::addValue(1);
Two.h
struct Two{};
Two.cpp
#include "Two.h"
#include "GlobalSet.h"
void* globalset2 =GlobalSet::addValue(2);
test.cpp
int main(){
return 0;
}
But this program will cause segment fault depend on cpp sequence in gcc compile command:
g++ GlobalSet.cpp One.cpp Two.cpp test.cpp -o test.exe //normal
g++ One.cpp Two.cpp GlobalSet.cpp test.cpp -o test.exe //segment fault!!
Why would it happen? How to fix the problem so that it works without care the sequence of cpp in gcc compilation?
Welcome to the Static Initialization Order Fiasco.
The C++ standard does not guarantee the initialization order of global objects in multiple translation units.
Depending on your link order, your code will attempt to construct globalset2 first. However, this calls a static class method addValue(), which attempts to access a std::set that has not been constructed, yet.
Undefined behavior, and a crash.
To fix this, go to www.google.com, search for "static initialization order fiasco", and keep reading, until you understand the issue. Once you do, you will know what to do to fix it, in your code.

Boost.Python - Exposing a class

I have the following class called "Wav" which is stored in another directory, with the files "Wav.h" and "Wav.cpp" and looks like the following:
enum ReadType {
NATIVE = 0,
DOUBLE,
};
namespace AudioLib {
class Wav : public Signal {
public:
Wav();
Wav(const int M, const int N);
///... ->
};
};
The .cpp file contains the implementation of this class, everything compiles well.
I'm trying to implement a Python wrapper using boost.python and have the following file:
#include <boost/python.hpp>
#include "../src/Wav/Wav.h"
using namespace boost::python;
BOOST_PYTHON_MODULE(Wav)
{
class_<AudioLib::Wav>("Wav",
init<const int, const int>());
}
In my Makefile, I am compiling the Wav.cpp:
# Compile the .wav Python and Cpp file
$(WAV_TARGET).so: $(WAV_TARGET).o
g++ -shared -Wl,--export-dynamic $(WAV_TARGET).o -L$(BOOST_LIB) -lboost_python -
lboost_python -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) -o
$(WAV_TARGET).so
$(WAV_TARGET).o: $(WAV_TARGET).cpp
g++ $(CFLAGS) ../src/Wav/Wav.cpp -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -fPIC -c
$(WAV_TARGET).cpp
And whenever I try to import into Python I get the following:
ImportError: Wav.so: undefined symbol: _ZN8AudioLib3WavC1Eii
Where am I going wrong?
It looks like you have failed to define the second constructor:
Wav(const int M, const int N);
I can replicate the error message by making a working (but simplified) copy of your example with in-line definitions and just removing the definition of that constructor. So my advice would be to check carefully for the definition in Wav.cpp and try creating an in-line definition to experiment.
If the definition does exist, maybe the linker flags are not right.

undefined reference compiler error in c++

I am getting the error message below when I try to compile my code -
In function
'__static_initialization_and_destruction_0':
home/user/main.cpp:50: undefined
reference to
'PhysEng2D::PhysEng2D(void)'
The only code on line 50 is -
PhysEng2D Physics;
The header file for PhysEng2D is -
#ifndef _PHYSENG2D_H_
#define _PHYSENG2D_H_
#include "primitives.h"
class PhysEng2D
{
public:
PhysEng2D::PhysEng2D();
PhysEng2D::~PhysEng2D();
bool IsBoundingBoxCollision(PS2Sprite & S1, PS2Sprite & S2);
bool IsWallCollision(PS2Sprite & S);
};
#endif
And the beginning of the rest of PhysEng2D is -
#include "primitives.h"
#include "physeng2d.h"
PhysEng2D::PhysEng2D()
{
//Nothing to Initialise
}
PhysEng2D::~PhysEng2D()
{
//Nothing to clean up
}
(I didn't include the methods in full because I didn't think they were relevant)
Sorry, I am aware that this is probably a very stupid little error that I'm making.
Your constructor and destructor in the header file should not contain the name of the class.
Change
PhysEng2D::PhysEng2D();
PhysEng2D::~PhysEng2D();
To
PhysEndg2D();
~PhysEng2D();
And you don't need to reinclude "primitives.h" in the .cpp.
You need to compile each cpp file, then link them.
g++ -c -Wall main.cpp
g++ -c -Wall physeng2d.cpp
g++ -o myapp main.o physeng2d.o
You also should remove the PhysEng2D:: prefix from the class definition in the .h
It looks like you forgot to link PhysEng2D.o with main.o. Also PhysEng2D::PhysEng2D(); syntax isn't valid inside the class definition: It should just say PhysEng2D();.