C++: Undefined referense to class::function() - c++

i been having a problem that i tried for many days to fix but i cant find a solution for it.
I keep getting this Error:
undefined reference to 'Simulator::Simulator(int, int)'
undefined reference to 'Simulator::run();'
undefined reference to 'Simulator::~Simulator()'
undefined reference to 'Simulator::~Simulator()'
I searched for an answer but nothing seems to be working for me.
Here are my classes:
main.cpp:
#include <iostream>
#include <cstdlib>
#include "Simulator.h"
int main(int argc, char** argv) {
//Some code
Simulator sim(rows, cols);
sim.run();
}
Simulator.h:
#include <iostream>
#include "PersonQueue.h"
#include "DogQueue.h"
class Simulator {
void drawBoard();
DogQueue _dq;
PersonQueue _pq;
public:
int dog_num, person_num;//Number of entitys
int _rows, _cols;//Should be static but wont work.
void fill_queue();//check
void init_clrs();
Simulator(int rows, int cols);//check
void run();//check
~Simulator();
};
Simulator.cpp:
#ifndef SIM_C
#define SIM_C
#include <iostream>
#include <curses.h>
#include "Simulator.h"
int Simulator:: _rows;
int Simulator:: _cols;
Simulator::Simulator(int row, int col) {
_rows = row;
_cols = col;
dog_num = 2; //number of dog entitys
person_num = 2;//number of person entitys
}
void Simulator::init_clrs() {
//some code...
}
void Simulator::drawBoard() {
//some code...
}
void Simulator::fill_queue() {
//some code...
}
void Simulator::run() {
initscr();
start_color();
Simulator::init_clrs();
Simulator::fill_queue();
Simulator::drawBoard();
while (std::cin.get() != (char)27) {
Person* person_obj = _pq.dequeue();
Dog* dog_obj = _dq.dequeue();
person_obj->Person::advance();
dog_obj->Dog::advance();
if (dog_obj->steps == MAX_STEP && person_obj->steps) {
_dq.enqueue(dog_obj);
_pq.enqueue(person_obj);
}
refresh();
}
}
Simulator::~Simulator() {//To_be_changed
delete this;
}
#endif
From what i read i believe the problem may be with the makefile but it seems ok and works until i get the undefined error.
makefile just in case:
tester: main.o simulator.o personqueue.o dogqueue.o character.o person.o dog.o
g++ -Wall main.cpp -lncurses -o tester
main.o: main.cpp
g++ -c -Wall main.cpp -o main.o
simulator.o: Simulator.cpp Simulator.h
g++ -c -Wall Simulator.cpp Simulator.h -o simulator.o
character.o: Character.cpp Character.h
g++ -c -Wall Character.cpp Character.h -o character.o
person.o: Person.cpp Person.h
g++ -c -Wall Person.cpp Person.h -o person.o
dog.o: Dog.cpp Dog.h
g++ -c -Wall Dog.cpp Dog.h -o dog.o
personqueue.o: PersonQueue.cpp PersonQueue.h
g++ -c -Wall PersonQueue.cpp PersonQueue.h -o personqueue.o
dogqueue.o: DogQueue.cpp DogQueue.h
g++ -c -Wall DogQueue.cpp DogQueue.h -o dogqueue.o
clean:
rm -rf *.o tester
Thank you for any input on this issue.
EDIT:
I dont believe the problem is with DogQueue or Person queue as all they include is Dog.h Person.h
but anyways just to be sure:
#include "DogQueue.h"
#include <cstdlib>
//Some code...
#include "PersonQueue.h"
#include <cstdlib>
//some code...

i think you have issues in your make file,
tester: main.o simulator.o personqueue.o dogqueue.o character.o person.o dog.o
g++ -Wall main.cpp -lncurses -o tester
try something like this, though I have not tested the code,
tester: main.o simulator.o personqueue.o dogqueue.o character.o person.o dog.o
g++ -o tester main.o simulator.o personqueue.o dogqueue.o character.o person.o dog.o -lncurses

Related

Changing the variable defined in shared library in my program doesn't get reflected seen from the shared library

Trying to test a simple case where a global variable defined in a shared library is set by a program and used by the shared library, I saw a strange problem. Here are the program codes.
bar.cpp
#include <stdint.h>
#include <stdio.h>
extern "C" {
uint64_t var_from_lib;
}
class BC;
class BC {
public:
void bar(void);
BC();
~BC();
};
BC::BC()
{
}
BC::~BC()
{
}
void BC::bar(void)
{
printf("class function : var_from_lib = %lx\n", var_from_lib);
}
extern "C" {
void bar(void)
{
printf("global function : var_from_lib = %lx\n", var_from_lib);
BC tmp;
tmp.bar();
}
}
main1.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib;
int main1(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
var_from_lib = 0x12341111;
bar();
return 0;
}
main2.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib;
int main2(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
var_from_lib = 0x12342222;
bar();
return 0;
}
main.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib; // = 0x12345678;
uint64_t __attribute__((weak)) var_from_lib; // = 0x12345678;
extern int main1();
extern int main2();
int main(int argc, char *argv[])
{
if (atoi(argv[1]) == 1) {
main1();
}
else if (atoi(argv[1]) == 2) {
main2();
}
else {
printf("usage : main [1|2]\n");
}
return 0;
}
Makefile
.PHONY: all clean test
LDEXTRAFLAGS ?=
all: prog
%.o: %.c
gcc -c -Wall -fpic -g -o $# -ldl $<
%.o: %.cpp
g++ -c -Wall -fpic -g -o $# $<
libbar.so: bar.o
g++ -shared -o $# $<
prog: main.o main1.o main2.o | libbar.so
gcc $(LDEXTRAFLAGS) -o $# $^ -ldl
clean:
rm -f *.o *.so prog
And here is the build and execution result which is different from what I thought.
ckim#ckim-ubuntu:~/testdir$ make
gcc -c -Wall -fpic -g -o main.o -ldl main.c
gcc -c -Wall -fpic -g -o main1.o -ldl main1.c
gcc -c -Wall -fpic -g -o main2.o -ldl main2.c
g++ -c -Wall -fpic -g -o bar.o bar.cpp
g++ -shared -o libbar.so bar.o
gcc -o prog main.o main1.o main2.o -ldl
ckim#ckim-ubuntu:~/testdir$ prog 1
global function : var_from_lib = 0
class function : var_from_lib = 0
The main1() changes the var_from_lib to 0x12341111 and main2() changes the variable to 0x12342222. I expected the changed values will be observed from inside the shared library but it is not!
I used debugger and checked the address of var_from_lib and it was the same seen from main.c and seen from bar.cpp. What could be wrong here?
Looks like you are not linking to the shared library. You are dlopen-ing it.
Your expected behavior works like this only when you are directly linking with the shared library.
With dlopen you are expected to do all the work yourself: using dlsym to obtain the address of a symbol that's defined by the shared library.

Can't find the source of the error: 'Undefined symbols for architecture x86_64' Makefile

I am getting this error:
g++ -c location.cpp
g++ -c place.cpp
g++ -c popularplace.cpp
g++ -c person.cpp
g++ -o main main.cpp *.o
Undefined symbols for architecture x86_64:
"sim::PopularPlace::arraycounter", referenced from:
sim::PopularPlace::PopularPlace() in popularplace.o
sim::PopularPlace::PopularPlace(double, double) in popularplace.o
"sim::PopularPlace::places", referenced from:
sim::Person::action() in person.o
sim::PopularPlace::PopularPlace() in popularplace.o
sim::PopularPlace::PopularPlace(double, double) in popularplace.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1
When building this makefile:
main: main.cpp simulation.h location.o place.o popularplace.o person.o
g++ -o main main.cpp *.o
location.o: location.cpp location.hpp simulation.h
g++ -c location.cpp
place.o: place.hpp place.cpp
g++ -c place.cpp
popularplace.o: place.hpp place.cpp simulation.h popularplace.hpp popularplace.cpp
g++ -c popularplace.cpp
person.o: person.cpp person.hpp location.hpp simulation.h place.hpp place.cpp location.cpp popularplace.o
g++ -c person.cpp
clean:
rm *.o
I can't find the error. Here is the popularplace.cpp file:
#include "popularplace.hpp"
#include "simulation.h"
namespace sim{
PopularPlace::PopularPlace()
:open(true){
places[PopularPlace::arraycounter] = this;
PopularPlace::arraycounter++;
}
PopularPlace::PopularPlace(double x, double y)
:Place(x, y), open(true){
places[PopularPlace::arraycounter] = this;
PopularPlace::arraycounter++;
}
bool PopularPlace::isOpen() const{
return open;
}
void PopularPlace::close(int numOfCasesToReopen){
open = false;
}
bool PopularPlace::reopen(int activeCases){
if(activeCases <= numOfCasesToReopen){
open = true;
return true;
} else{
return false;
}
}
}
and here's the popularplace.hpp file:
#ifndef POPULAR_PLACE_HPP
#define POPULAR_PLACE_HPP
#include "simulation.h"
#include "place.hpp"
namespace sim{
class PopularPlace : public Place{
private:
bool open;
int numOfCasesToReopen;
static int arraycounter;
public:
static PopularPlace* places[POPULAR_PLACES];
PopularPlace();
PopularPlace(double x, double y);
bool isOpen() const;
void close(int numOfCasesToReopen);
bool reopen(int activeCases);
};
}
#endif
If you need me to provide additional information/code, I'd be happy to do so. Thanks.
Static variables need a definition; they are declared in the header but they should also be defined in the cpp file. This is also where you'd initialize them. For example:
int PopularPlace::arraycounter{0};
PopularPlace* PopularPlace::places[POPULAR_PLACES] = {};
However, you might consider using an std::vector<std::shared_ptr<PopularPlace>> instead of a manually-managed array.

gcc --version-script cannot recognize int64_t

The code examples explain the problem fairly straightforward:
Hash.h
#include <iostream>
#include <cstdint>
using namespace std;
class Hash {
public:
Hash(int64_t sz);
int64_t size;
};
Hash.cpp
#include "Hash.h"
using namespace std;
Hash::Hash(int64_t sz) : size(sz)
{
cout << "Hash int" << endl;
}
main.cpp
#include "Hash.h"
using namespace std;
int main(int argc, char *argv[])
{
Hash HashTable(12);
return 0;
}
And here is the version file, foo.map:
VER_0.1
{
global:
extern "C++" {
"Hash::Hash(int64_t)";
};
local:
*;
};
For the compilation:
$g++ -g -c -Wall -Werror -fpic Hash.cpp -std=c++0x
$g++ -shared -o Hash.so Hash.o -std=c++0x -Wl,--version-script=foo.map
$g++ -g -o prog Hash.so main.cpp -std=c++0x
The error message:
/tmp/ccd60Ulm.o: In function `main':
/remote/ltg_engine1_us03/liangwa/test/004/main.cpp:7: undefined reference to `Hash::Hash(long)'
collect2: error: ld returned 1 exit status
Then if I change all int64_t to int or long, it compiles fine. So anything special with int64_t? I am using g++ 7.3.0

Geany - undefined reference

I am trying to compile C++ code with Geany.
Compile command: g++ -Wall -c "%f"
Build command: g++ -Wall -o "%e" "%f"
main.cpp:
#include <iostream>
#include "Person.hpp"
int main()
{
Person p1(16);
std::cout << p1.getAge();
return 0;
}
Person.hpp
class Person
{
public:
Person(int a);
void setAge(int);
int getAge() const;
private:
int age;
};
inline int Person::getAge() const
{
return age;
}
Person.cpp
#include "Person.hpp"
Person::Person(int a)
{
age = a;
}
void Person::setAge(int a)
{
age = a;
}
Error:
g++ -Wall -o "main" "main.cpp" (in directory:
/home/me/projects/Test) /tmp/ccxYmWkE.o: In function main':
main.cpp:(.text+0x15): undefined reference toPerson::Person(int)'
collect2: error: ld returned 1 exit status Compilation failed.
Before Geany, I only used Code::Blocks and everything worked fine. How can I fix it?
It's obvious you didn't add Person.cpp to the compilation command. then it can not pass the linkage level.
Add -o Person Person.cpp to the build option after g++ -Wall -c "%e" "%f".
After all the compile command should be something like below:
g++ -Wall -o "main" "main.cpp" -o Person Person.cpp

C++ linking object's files (G++)

class.h
#include <iostream>
#include <stdint.h>
using namespace std;
template <typename T>
class CIntegerType {
public:
void Show ( void );
private:
T m_Data;
};
class.cpp
#include "class.h"
template <typename T>
void CIntegerType<T> :: Show ( void ) {
cout << m_Data << endl;
}
main.cpp
#include "class.h"
int main ( void ) {
CIntegerType<uint32_t> UINT32;
UINT32 . Show ();
return 0;
}
This commands return:
g++ -Wall -pedantic -c main.cpp
g++ -Wall -pedantic -c class.cpp
g++ -Wall -pedantic -o class.o main.o
main.o: In function `main':
main.cpp:(.text+0x11): undefined reference to 'CIntegerType< unsigned int>::Show()'
collect2: ld returned 1 exit status
Try putting your template implementation in the header file.
See: Why can templates only be implemented in the header file?
Try g++ -Wall -pedantic -o main.o class.o instead. You are facing the same problem as in this question: g++ linking order dependency when linking c code to c++ code
The linker searches for functions in the order they appear. Since you have a template function, its use in main must be fed to the linker prior to the actual code to instantiate it in class.