How to fix : 'undefined reference to foo()' with Makefile and g++ - c++

I've been trying to get into C++ again, and I have a linker error when I try to compile :
main.cpp:(.text+0x92): undefined reference to `eval(std::string, double, double, double)'
I've already tried compiling each file separatly and then linking by hand but it never works.
I have tried numerous solutions provided by other similar posts but none of these work and I don't have any idea on how to fix my problem (which doesn't seem to be that hard)
main.cpp :
#define _GLIBCXX_USE_CXX11_ABI 0
#include <iostream>
#include "functions.h"
int main()
{
std::string expression = "1/2+x";
double x = 1.45;
double y = 1.65;
double z = 1.77;
double result = 0.0;
result = eval(expression,x,y,z);
std::cout << result << std::endl;
return 0;
}
functions.cpp :
#include "functions.h"
double eval(std::string expression_s, double x, double y, double z)
{
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
symbol_table_t symbol_table0;
symbol_table_t symbol_table1;
symbol_table_t symbol_table2;
expression_t expression;
parser_t parser;
symbol_table0.add_variable("x",x);
symbol_table1.add_variable("y",y);
symbol_table2.add_variable("z",z);
expression.register_symbol_table(symbol_table0);
expression.register_symbol_table(symbol_table1);
expression.register_symbol_table(symbol_table2);
parser.compile(expression_s,expression);
std::cout << expression.value();
return expression.value();
}
functions.hpp :
ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
#include "exprtk/exprtk.hpp"
#include <iostream>
double eval(std::string expression_s, double x, double y, double z);
#endif
Makefile :
CC = g++
EXEC = Crystal_MET
LIBS =
FLAGS =
all: main.o
$(CC) *.o -o $(EXEC) $(LIBS)
main.o : functions.o main.cpp functions.h
$(CC) main.cpp -c $(FLAGS)
functions.o : functions.cpp functions.h
$(CC) functions.cpp -c $(FLAGS)
clear :
rm -f *.o
mr_proper :
rm -f *.o $(EXEC)

main.cpp is compiled against a different ABI than functions.cpp because of :
#define _GLIBCXX_USE_CXX11_ABI 0
Either remove that line from main.cpp, or add it to functions.cpp .
More details : https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

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.

Strange error with the Test_F and EXPECT_EQ functions of GTEST

I'm trying to implement an extremely simple GoogleTest example in VScode on Linux and I'm getting some weird errors that I cannot find online. When I'm trying to actually define the tests that will be run -
'''
#include <limits.h>
#include "gtest/gtest.h"
#include </home/tester/src/Multiply.h>
class MultiplyTest : public ::testing::Test {
protected:
virtual void SetUp() {
}
virtual void TearDown() {
}
};
TEST_F(MultiplyTest,twoValues){
const int x = 4;
const int y = 5;
Multiply multiply;
EXPECT_EQ(20,multiply.twoValues(x,y));
EXPECT_EQ(6,multiply.twoValues(2,3));
}
'''
Errors get thrown at the TEST_F and EXPECT_EQ parts, saying specifically that TEST_F is "this declaration has no storage class or type specifier" and EXPECT_EQ is "class "testing::internal::EqHelper" has no member "Compare"."
Any help would be greatly appreciated.
Here is my multiply.h header file:
#ifndef _MULTIPLY_HPP_
#define _MULTIPLY_HPP_
class Multiply{
public:
static int twoValues(const int x, const int y);
};
#endif
and my makefile:
CXX = gcc
CXXFLAGS = -g -L/opt/gtest/lib -lgtest -lgtest_main -lpthread
INCS = -I./ -I../../src -I/opt/gtest/include
OBJS = ../../src/Addition.o Addition_Test.o ../../src/Multiply.o Multiply_Test.o
testAll: $(OBJS)
$(CXX) $(CXXFLAGS) $(INCS) -o testAll Main_TestAll.cpp $(OBJS)
.cpp.o:
$(CXX) $(CXXFLAGS) -c $< -o $# $(INCS)
clean:
rm testAll *.o testAll.xml
I'm currently running gcc 7.3.1 if that helps.

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

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

undefined reference to `vtable for implementation' error

I wrote some c++ files and after compiling with out make file it works fine . But when using make file it pop out some errors . My codes are :
include directory files :
application.h
#ifndef APPLICATION_H
#define APPLICATION_H
#include "employee.h"
#include "employee_data.h"
#include "employee.h"
...some defintions here...
#endif
employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include "employee_data.h"
#endif
employee_data.h
#ifndef EMPLOYEE_DATA_H
#define EMPLOYEE_DATA_H
typedef struct
{
int emp_id;
char *name,
*dept,
*book,
*time;
}employeedata;
...some codes here...
#endif
library.h
#ifndef LIBRARY_H
#define LIBRARY_H
#include "employee_data.h"
#include "application.h"
using namespace std;
class Library
{
public:
virtual int addE() = 0;
virtual int deleteE() = 0;
virtual int issue() = 0 ;
virtual int returnB() = 0;
virtual int employee() = 0;
};
class implementation : public Library
{
private:
employeedata *emp; /*structure object*/
public:
int addE();
int deleteE();
int issue();
int returnB();
int employee();
};
#endif
main.h
#ifndef MAIN_H
#define MAIN_H
#include "library.h"
class message
{
public:
void errormessage(int);
};
#endif
and my src directory conatins .cpp files . It includes
main.cpp
#include "main.h"
#include "library.h"
#include "employee_data.h"
#include "application.h"
int main()
{
message msg;
/* codes here..../*
}
library_function.cpp
#include "library.h"
#include "employee.h"
#include "main.h"
#include "application.h"
#include "employee_data.h"
int implementation :: addE()
{
}
etc..
error_function.cpp
#include "main.h"
void message :: errormessage(int errno)
{
}
employee_functions.cpp
#include "employee.h"
#include "main.h"
..some code...
display.cpp
#include "employee_data.h"
#include "application.h"
..some code..
thread.cpp
#include "employee.h"
#include "application.h"
...some code..
and my make file is :
CC=g++
FLAGS=-o
CFLAGES=-c -Wall
THREAD=-lpthread
INCLUDE=../include/
SRC=../src/
OBJ=../obj/
OUTPUT=../bin/
$(OUTPUT)vkp:$(OBJ)main.o $(OBJ)library_functions.o $(OBJ)employee_functions.o $(OBJ)display.o $(OBJ)error_function.o $(OBJ)thread.o
$(CC) $(FLAGS) vkp $(OBJ)main.o $(OBJ)library_functions.o $(OBJ)employee_functions.o $(OBJ)display.o $(OBJ)error_function.o $(OBJ)thread.o $(THREAD)
mv vkp $(OUTPUT)
$(OBJ)main.o:$(SRC)main.cpp $(INCLUDE)main.h $(INCLUDE)employee_data.h $(INCLUDE)application.h
$(CC) $(CFLAGS) $(SRC)main.cpp -I $(INCLUDE)
mv main.o $(OBJ)
$(OBJ)library_functions.o:$(SRC)library_functions.cpp $(INCLUDE)library.h $(INCLUDE)employee.h $(INCLUDE)main.h $(INCLUDE)application.h $(INCLUDE)employee_data.h
$(CC) $(CFLAGS) $(SRC)library_functions.cpp -I $(INCLUDE)
mv main.o $(OBJ)
$(OBJ)employee_functions.o:$(SRC)employee_functions.cpp $(INCLUDE)employee.h $(INCLUDE)main.h
$(CC) $(CFLAGS) $(SRC)employee_functions.cpp -I $(INCLUDE)
mv main.o $(OBJ)
$(OBJ)display.o:$(SRC)display.cpp $(INCLUDE)employee_data.h $(INCLUDE)application.h
$(CC) $(CFLAGS) $(SRC)display.cpp -I $(INCLUDE)
mv main.o $(OBJ)
$(OBJ)error_function.o :$(SRC)error_function.cpp $(INCLUDE)main.h
$(CC) $(CFLAGS) $(SRC)error_function.cpp -I $(INCLUDE)
mv main.o $(OBJ)
$(OBJ)thread.o:$(SRC)thread.cpp $(INCLUDE)employee.h $(INCLUDE)application.h
$(CC) $(CFLAGS) $(SRC)thread.cpp -I $(INCLUDE)
mv main.o $(OBJ)
After runing make i got eroor like :
g++ ../src/main.cpp -I ../include/
/tmp/cc09snhj.o: In function `main':
main.cpp:(.text+0x568): undefined reference to `message::errormessage(int)'
main.cpp:(.text+0x5fb): undefined reference to `message::errormessage(int)'
main.cpp:(.text+0x6c5): undefined reference to `message::errormessage(int)'
main.cpp:(.text+0x758): undefined reference to `message::errormessage(int)'
main.cpp:(.text+0x7f3): undefined reference to `message::errormessage(int)'
/tmp/cc09snhj.o: In function `implementation::implementation()':
main.cpp:(.text._ZN14implementationC2Ev[_ZN14implementationC5Ev]+0x1f): undefined reference to `vtable for implementation'
collect2: ld returned 1 exit status
make: *** [../obj/main.o] Error 1
what is wrong on my code ? any problem in make file ? I think the problem is linking the header files . Is this correct way to link header files ? Please help me to get my make file work .
I think you just misspelled CFLAGS in CFLAGES=-c -Wall
I'm guessing this is the case since
g++ ../src/main.cpp -I ../include/
does not have the -c option

Undefined reference to a user defined function

I have seen the standard Undefined Reference to thread from this site but I do not believe it solves my problem. I am not putting header guards on my .cpp files, but still get an undefined reference to a user defined function. Here are my files:
(1) pth_funs.h
// hello from thread <pid>
void* hello(void* ptr);
(2) pth_funs.cpp
#include <stdio.h>
void* hello(void *ptr)
{
char *message;
int pid = (long) ptr;
printf("Hello from thread %i\n", pid);
}
(3) structs.h
#ifndef STRUCTS_H
#define STRUCTS_H
struct grd_str {
long nx;
long ny;
long natoms;
char** atnames;
double* xs;
double* ys;
double** fs;
double** xyzs;
};
#endif
(4) fio.h
#ifndef FIO_H
#define FIO_H
#include <iostream>
#include <string.h>
#include "structs.h"
void read_grd(std::string, grd_str);
#endif
(5) fio.cpp
#include <string.h>
#include "structs.h"
#include "fio.h"
void read_grd( std::string fname, grd_str &grd)
{
grd.nx = 10;
grd.ny = 10;
}
(6) and finally, xdriver.cpp
#include <iostream> // needed for cout, endl, etc
using namespace std; // needed for cout, endl, etc
#include <pthread.h> // needed for pthreads
#include <string.h> // string handling
#include "pth_funs.h" // pthread function headers
#include "structs.h"
#include "fio.h"
int main(int argc, char** argv)
{
// thread stuff
int nthreads = 4;
pthread_t rank[4];
int iret[4];
// file stuff
string base_dir = "D:\\cygwin64\\home\\Robert\\code\\C\\form_reconstruction\\data\\";
string fname;
// topology stuff
int nx, ny;
double* xs;
double* ys;
double** fs;
grd_str grd;
for(long tid = 0; tid < nthreads; tid++)
{ iret[tid] = pthread_create( &rank[tid], NULL, hello, (void*) tid); }
fname = base_dir;
fname.append("adf\\adf.6.grd");
cout << "Filename: " << fname << endl;
read_grd(fname, grd);
}
I am compiling this using a Makefile which is as follows:
cc=g++
exe=create_grd.exe
flags=-pthread
hds= pth_funs.h fio.h structs.h
objs= pth_funs.o fio.o
all: create_grd.exe
create_grd.exe: xdriver.cpp $(hds) $(objs)
$(cc) -o $(exe) $(objs) xdriver.cpp
pth_funs.o: pth_funs.cpp pth_funs.h
$(cc) -c pth_funs.cpp $(flags)
fio.o: fio.cpp fio.h
$(cc) -c fio.cpp $(flags)
clean:
rm -rf *.o
However, upon compilation I get
g++ -c pth_funs.cpp -lpthread
g++ -c fio.cpp -lpthread
g++ -o create_grd.exe pth_funs.o fio.o xdriver.cpp -lpthread
/tmp/ccdaBayB.o: In function `main':
xdriver.cpp:(.text+0x16f): undefined reference to `read_grd(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, grd_str)'
collect2: ld returned 1 exit status
make: *** [create_grd.exe] Error 1
but I have no idea why my main routine can't find read_grd since I believe I am properly defining it and including it. What am I doing wrong?
Your declaration and definition of read_grd do not have matching arguments. One takes a grd_str as its second argument, the other takes a grd_str&. Since xdriver.cpp includes fio.h, it sees and attempts to use the former function, but the linker can't find a definition for it anywhere. Chances are you want to change your declaration in fio.h to:
void read_grd(std::string, grd_str&);
Now the definition for this function is provided by fio.cpp.