undefined reference to functions that have implementation [duplicate] - c++

This question already has answers here:
Undefined reference to pthread_create in Linux
(16 answers)
Closed 3 years ago.
I'm using a class of threads with a header and cpp file.
When I put both of them and empty test file it writes:
g++ -g -pedantic -ansi -Wall -Werror -std=c++03 -I../include -c -o test.o test.cpp
g++ -g test.o thread.o -o test
thread.o: In function `Thread::~Thread()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:15: undefined reference to `pthread_detach'
thread.o: In function `Thread::start()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:40: undefined reference to `pthread_create'
thread.o: In function `Thread::join()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:49: undefined reference to `pthread_join'
thread.o: In function `Thread::cancel()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:58: undefined reference to `pthread_cancel'
thread.o: In function `Thread::detach()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:66: undefined reference to `pthread_detach'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'test' failed
make: *** [test] Error 1
I just tried to comppile Thread.h and Thread.cpp
//Thread.h looks like this:
#ifndef THREAD_H
#define THREAD_H
#include <cstddef>
#include <pthread.h>
#include <string>
class Thread
{
public:
Thread(size_t a_userID = 0);
virtual ~Thread();
bool start();
void join();
void cancel();
void detach();
private:
static void* threadMainFunction(void *);
virtual void run() = 0;
bool isAlive(std::string a_msg);
private:
bool m_joinable;
protected:
pthread_t m_threadID;
size_t m_userID;
};
#endif
//Thread.cpp looks like this:
#include <exception>
#include "Thread.h"
#include <iostream>
Thread::Thread(size_t a_userID)
: m_joinable(true)
, m_threadID(0)
, m_userID(a_userID)
{
}
Thread::~Thread()
{
if(m_joinable)
{
pthread_detach(m_threadID);
}
}
void* Thread::threadMainFunction(void *a_thread)
{
Thread* thread = reinterpret_cast<Thread*>(a_thread);
try
{
thread->run();
}
catch(const std::exception& e)
{
std::cout<<"what exepction\n";
std::cerr << e.what() << '\n';
}
catch(...)
{
throw;
}
return 0;
}
bool Thread::start()
{
int r = pthread_create(&m_threadID, 0, threadMainFunction, this);
return r == 0;
}
void Thread::join()
{
if(isAlive("Thread::join on thread not started"))
{
void *status;
pthread_join(m_threadID, &status);
m_joinable = false;
}
}
void Thread::cancel()
{
if(isAlive("Thread::cancel on thread not started"))
{
pthread_cancel(m_threadID);
}
}
void Thread::detach()
{
if(isAlive("Thread::detach on thread not started"))
{
pthread_detach(m_threadID);
}
}
bool Thread::isAlive(std::string a_msg)
{
if(m_threadID == 0)
{
throw(std::runtime_error(a_msg));
return false;
}
return true;
}

The issue you are facing here is not a build issue, but a link issue. When building thread.o, the compiler knows pthread_create exists and is defined somewhere because declared in the pthread.h header.
If you used nm to look at the symbols used in thread.o, you would see something similar to this:
U _pthread_create
U _pthread_detach
...
This tells you that thread.o references multiple Undefined symbols including pthread_create. In other words, the machine code for pthread_create is unknown at this point. This is perfectly fine until you need to link your object files into an executable file, which is the role of the linker.
At this stage, you must tell the linker where to find these undefined symbols, perhaps from another object file or a static/shared library. For pthread, the symbols are defined in libpthread, which you can likely find in a system directory as libpthread.a. You can tell g++ to link this library by adding -lpthread (note that lib from libpthread is omitted when using -l):
g++ -g test.o thread.o -o test -lpthread
In general, if you use symbols referenced in a static library lib${LIBNAME}.a available in ${LIBDIR} directory, you can tell the linker to use it with:
g++ -g *.o -L$LIBDIR -l${LIBNAME}

Related

Why does this C++ program have problems linking with undefined reference error?

For some reason, I'm having a lot of trouble lately with creating classes with multiple files because an undefined reference error keeps showing up.
Here's the code:
Card.h
class Card {
char name;
public:
char getName();
void setName(char);
Card();
Card(char);
};
Card.cpp
#include "Card.h"
Card::Card()
{
name = '-';
}
Card::Card(char _name)
{
name = _name;
}
void Card::setName(char _name)
{
name = _name;
}
char Card::getName()
{
return name;
}
main.cpp
#include <iostream>
#include "Card.h"
int main()
{
std::cout << "Welcome to deck of cards!" << std::endl;
Card card;
card.setName('A');
std::cout << card.getName() << std::endl;
return 0;
}
I get the program running by compiling and building:
g++ -c *.cpp
g++ -o Card.o main.o
This is the error:
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x4b): undefined reference to `Card::Card()'
/usr/bin/ld: main.cpp:(.text+0x5c): undefined reference to `Card::setName(char)'
/usr/bin/ld: main.cpp:(.text+0x68): undefined reference to `Card::getName()'
collect2: error: ld returned 1 exit status
I know it has something to do with the linker not recognizing the methods. But the methods exist, right?
Instead of g++ -o Card.o main.o you want g++ -o Card Card.o main.o
The doc says:
-o <file>
So, the -o option takes an output file. This is preventing you from linking Card.o in.

Order when linking object files and static libraries

I have created 2 object files hello.o and hi.o, each containing a function with the same name, respectively. Also, greetings.h was created containing the function prototypes of the two object files.
When I link these two object files with main.o in any order, the process succeeds and I get a.out. But if you make a static library from the hello.o and hi.o files, then the linking succeeds only in the order g++ main.o glib.a.
As I understand it, the order should be from the file that declares to the file that contains the definition, but when linking object files alone, it doesn't work. What is the difference between linking a library and object files, and only object files?
Example:
Source code:
greetings.hpp
#ifndef GREETINGS_HPP
#define GREETINGS_HPP
void hello();
void hi();
#endif
hello.cpp
#include <iostream>
void hello() {
std::cout << "Hello!" << std::endl;
}
hi.cpp
#include <iostream>
void hi() {
std::cout << "Hi!" << std::endl;
}
main.cpp
#include "greetings.hpp"
int main () {
hello();
hi();
return 0;
}
Actions:
ar -src glib.a hello.o hi.o
g++ glib.a main.o
Error:
main.o: In function `main':
main.cpp:(.text+0x5): undefined reference to `hello()'
main.cpp:(.text+0xa): undefined reference to `hi()'
collect2: error: ld returned 1 exit status

undefined reference to dlopen

I have one C program which I want to load into my running C program. Following are the snippet
File : a.c
#include <stdio.h>
void abc() {
printf("This is abc\n");
}
File : mainFile.cpp
#include<stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *lib = dlopen("./a.so", RTLD_LAZY);
if (!lib) {
printf("dlopen failed: %s\n", dlerror());
return 1;
}
void (*f)() = dlsym(lib, "abc");
if (f) {
f();
} else {
printf("dlsym for f1 failed: %s\n", dlerror());
}
dlclose(lib);
return 0;
}
I am compiling with the following commands
gcc -fpic -g -shared -ldl -o a.so a.c
g++ -w mainFile.cpp -o mainFile
Output:
/tmp/cc9fYZaf.o: In function `main':
mainFile.cpp:(.text+0x1a): undefined reference to `dlopen'
collect2: error: ld returned 1 exit status
I am compiling in Ubuntu 16.04 with gcc version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
Please help
Note: I have followed the following references but none helped.
Can you dynamically compile and link/load C code into a C program?
undefined reference to `dlopen' since ubuntu upgrade
undefined reference to `dlopen'
The second line — the one which links the executable — needs the -ldl, not the first:
g++ -w mainFile.cpp -ldl -o mainFile

Undefined reference to function (linker error)

Hi i read the other questions and answers about undefined reference.But still i'm not able to find out what are the problems with my code. I have a simple linked list code wherein i add the integers to the tail and after that i display them. Here is my code
"head.h"
#ifndef __HEAD_H_INCLUDE
#define __HEAD_H_INCLUDE
class Node {
int info;
Node *next;
};
class imple {
public:
imple();
void addToTail(int );
void display(void);
private:
Node *head,*tail;
};
#endif
"implementaion.cpp"
#include<iostream>
#include "head.h"
imple::imple(){
head=tail=0;
}
void imple::addToTail(int key){
if(tail==0)
{tail=head=new Node();
info=key;next=0;}
else
{
tail->next=new Node();
info=key;next=0;
tail=tail->next;
}
}
void imple::display(){
Node *temp;
for(temp=head;temp->next !=0;temp=temp->next)
{
std::cout<<temp->info << " ";
}
}
"main.cpp"
#include<iostream>
#include "head.h"
int main(){
Node node;
imple ab;
for(int i=0;i<5;i++)
ab.addToTail(i);
ab.display();
}
Everytime i compile i get this error
"/tmp/cc20Z1ZH.o: In function main':
lmain.cpp:(.text+0x10): undefined reference toimple::imple()'
lmain.cpp:(.text+0x2a): undefined reference to imple::addToTail(int)'
lmain.cpp:(.text+0x45): undefined reference toimple::display()'
collect2: ld returned 1 exit status"
Your answers and suggestions will be helpful
In short, you may use
g++ main.cpp implementation.cpp -o out
You need to include implementation.cppin your building process and make the function definitions accessible to the linker. That is, compile it with
g++ -c implementation.cpp -o implementation.o
and
g++ -c main.cpp -o main.o
and link them together with
g++ main.o implementation.o -o out
Try using
g++ main.cpp implementaion.cpp
Probably this will help
You can create a run file with:
g++ -o main implementation.cpp main.cpp
and run it with :
./main

Undefined reference to a class::function in c++ [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
Working on a program where we must build a class for a stack and use it to check if strings are palindromes. Compiler is complaining about an undefined reference to the member functions in class Stack. I am not sure what I am doing wrong, as I believe I am using the exact same syntax as in the past. The files for the class are Stack02.h, Stack02.cpp, and p02.cpp is the main file for the program.
From Stack02.h
class Stack
{
int size;
int tos;
char* S;
public:
Stack(int sz=100); //Constructor
~Stack(); //Deconstructor
bool isFull(void);
bool isEmpty(void);
void Push(char v);
char Pop(void);
};
From Stack02.cpp:
#include "Stack02.h"
using namespace std;
//Exception handling for stacks
struct StackException
{
StackException{char* m}
{
cout << endl << "I am the Stack and I am " << m << "." << endl;
}
};
Stack::Stack(int sz):size(sz),tos(-1){S= new char[size]}; //Constructor
Stack::~Stack(){if(S) delete[] S;} //Deconstructor
bool Stack::isFull(void)
{
return tos >= size - 1;
} //Is the stack full?
bool Stack::isEmpty(void)
{
return tos < 0;
}
void Stack::Push(char v)
{
if(isFull) throw StackException("full");
S[++tos] = c;
}
char Stack::Pop(void)
{
if(isEmpty) throw StackException("empty");
return S[tos--];
}
The function the compiler is complaining about from p02.cpp:
bool IsPalindrome(string& c)
{
Stack s;
for (int a = 0; a < c.length(); a++) s.Push(c[a]);
for (int a = 0; !s.isEmpty() ;a < c.length())
{
if (c[a] !=s.Pop()) return false;
}
//can use default return value to check how output looks.
}
The makefile:
#------------------------------------------------
#Object files
#------------------------------------------------
obj = p02.o Stack02.o
#------------------------------------------------
#Link object files into executable file p02
#------------------------------------------------
p02: ${obj}
g++ -o p02 ${obj} -lm
#------------------------------------------------
#Compile p02.cpp that exercises class Stack
#------------------------------------------------
p02.o p02.cpp Stack02.h
g++ -g -c p02.cpp
#------------------------------------------------
#Compile Stack02.cpp that implements class Stack
#------------------------------------------------
Stack02.o Stack02.cpp Stack02.h
g++ -g -c Stack02.cpp
The compiler's complaints:
tt054#cs:~$ make p02
g++ p02.cpp -o p02
/tmp/ccYDuT0W.o: In function `IsPalindrome(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
p02.cpp:(.text+0x1c): undefined reference to `Stack::Stack(int)'
p02.cpp:(.text+0x4e): undefined reference to `Stack::Push(char)'
p02.cpp:(.text+0x9b): undefined reference to `Stack::Pop()'
p02.cpp:(.text+0xc9): undefined reference to `Stack::isEmpty()'
p02.cpp:(.text+0xe1): undefined reference to `Stack::~Stack()'
p02.cpp:(.text+0xfc): undefined reference to `Stack::~Stack()'
collect2: ld returned 1 exit status
make: *** [p02] Error 1
You're including the header file, but not building and linking the stack implementation. Try
g++ Stack02.cpp p02.cpp
Or replace g++ with whatever compiler you are using.