Undefined reference to my function - c++

I have some trouble with building the part of my project. Here it is:
utility.h:
#ifndef UTILITY_H
#define UTILITY_H
#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>
#include <fstream>
#include <iostream>
#include <openssl/md5.h>
#include <string>
namespace utility {
typedef boost::array<unsigned char, MD5_DIGEST_LENGTH> md5sum;
typedef boost::shared_ptr<md5sum> md5sum_ptr;
...
md5sum_ptr calculate_md5(const std::string& full_path);
};
#endif //UTILITY_H
utility.cpp:
#include "utility.h"
using namespace utility;
...
md5sum_ptr calculate_md5(const std::string& full_path) {
md5sum_ptr md5(new md5sum);
std::ifstream in(full_path);
std::string content;
in >> content;
MD5((unsigned char*)content.data(), content.size(), md5->data());
return md5;
}
cdaemon.cpp
void CTCPConnection::handle_read_filename(ECommand command, EDataType datatype,
const boost::system::error_code& ec) {
...
case ECommand::GET_MD5:
_send_container<md5sum>(*(calculate_md5(filename)));
async_write(m_socket, m_writebuf,
boost::bind(&CTCPConnection::handle_write_response, shared_from_this(),
placeholders::error));
break;
...
}
}
Makefile:
CC=g++
override CFLAGS+=-c -std=c++11 -Wall -Wextra -Werror
override LFLAGS+=-lboost_log -lpthread -lboost_system -lboost_thread -lcrypto
server: servermain.o cdaemon.o
$(CC) ../build/datatype.o ../build/utility.o build/servermain.o build/cdaemon.o -o build/frtpdaemon $(LFLAGS)
servermain.o: main.cpp
$(CC) $(CFLAGS) main.cpp -o build/servermain.o
cdaemon.o: cdaemon.cpp
$(CC) $(CFLAGS) -DBOOST_LOG_DYN_LINK cdaemon.cpp -o build/cdaemon.o
When I try to build server, I get linker error:
build/cdaemon.o: In function `CTCPConnection::handle_read_filename(utility::ECommand, utility::EDataType, boost::system::error_code const&)':
cdaemon.cpp:(.text+0x127c): undefined reference to `utility::calculate_md5(std::string const&)'
I have already tried to google the solution, but all what I could find were suggestions to change the order of ../build/utility.o and build/cdaemon.o. That didn't help me.

You don't define the function you have declared in the header. A using directive is insufficient when defining functions in a namespace. You'll either need to open the namespace before defining your function or qualify the function with the namespace, e.g.:
utility::md5sum_ptr utility::calculate_md5(const std::string& full_path) {
...
}

Related

LLVM opt cannot find function pass

Given the following function pass definition and registration:
// STL
#include <map>
#include <vector>
#include <utility>
// LLVM
#include <llvm/Pass.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/CFG.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/IR/Constants.h>
// For older versions of llvm you may have to include instead:
// #include "llvm/Support/CFG.h"
// #include <llvm/Support/InstIterator.h>
using namespace llvm;
namespace {
class DefinitionPass : public FunctionPass {
public:
static char ID;
DefinitionPass() : FunctionPass(ID) {}
virtual void getAnalysisUsage(AnalysisUsage &au) const {
au.setPreservesAll();
}
virtual bool runOnFunction(Function &F) {
// TODO
errs() << "def-pass\n";
return false;
}
};
class FixingPass : public FunctionPass {
public:
static char ID;
FixingPass() : FunctionPass(ID){}
virtual bool runOnFunction(Function &F){
// TODO
errs() << "fix-pass\n";
return true;
}
};
} // namespace
char DefinitionPass::ID = 0;
char FixingPass::ID = 1;
// Pass registrations
static RegisterPass<DefinitionPass> X("defpass", "Reaching definitions pass");
static RegisterPass<FixingPass> Y("fixpass", "Fixing initialization pass");
I compile this given the following makefile. The compilation is successful:
CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 -std=c++0x
all: p34.so
%.so: %.o
$(CXX) $(CXXFLAGS) -dylib -shared -fPIC $^ -o $#
clean:
rm -f *.o *~ *.so
Then I create the bitcode file for the file I want to analyse using:
clang -O3 -emit-llvm test1.c -c -o test1.bc
And use opt in the following way:
opt -load p34.so -defpass < test1.bc > /dev/null
But opt is unable to find the function pass "defpass":
opt: Unknown command line argument '-defpass'. Try: 'opt --help'
I'm on OSX and use the homebrew installed LLVM version.
Does anbody have an idea why opt cannot find the pass?
.so Files are for Linux/Unix. On MAC you should be using p34.dylib
Quoting "https://github.com/banach-space/llvm-tutor"
"Finally, run HelloWorld with opt (use libHelloWorld.so on Linux and libHelloWorld.dylib on Mac OS):"

Moving helper function to header file

In the beginning I had:
main.cpp
#include "something.h"
#include "util.h"
int main() {
sth::something();
utl::little_thing();
}
somehing.h
#ifndef SOMETHING_H
#define SOMETHING_H
namespace sth {
void something();
}
#endif
somehing.cpp
#include "something.h"
#include <string>
#include <iostream>
namespace sth {
void print_me(std::string txt) {
std::cout << txt << std::endl;
}
void something() {
std::cout << "this is something" << std::endl;
print_me("optional");
}
}
util.h
#ifndef UTIL_H
#define UTIL_H
namespace utl {
void little_thing();
}
#endif
util.cpp
#include "util.h"
#include <iostream>
#include <string>
namespace utl {
void little_thing() {
std::cout << "this is little thing" << std::endl;
}
}
Then I though it will be better to have print_me(std::string txt) out of sth namespace. And I put it on utl, declaration on .h file and definition on .cpp file.
At that point the lazy side of me said - would it be better to have it all in one file as was beofore. And I tried:
util.h
#ifndef UTIL_H
#define UTIL_H
#include <string>
#include <iostream>
namespace utl {
void little_thing();
void print_me(std::string txt) {
std::cout << txt << std::endl;
}
}
#endif
something.cpp
#include "something.h"
#include "util.h"
#include <string>
#include <iostream>
namespace sth {
void something() {
std::cout << "this is something" << std::endl;
utl::print_me("optional");
}
}
So I got:
c++ -std=gnu++14 -g -Wall -O3 -c -o main.o main.cpp
c++ -std=gnu++14 -g -Wall -O3 -c -o util.o util.cpp
c++ -std=gnu++14 -g -Wall -O3 -c -o something.o something.cpp
c++ main.o util.o something.o -o main
duplicate symbol __ZN3utl8print_meENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE in:
main.o
util.o
duplicate symbol __ZN3utl8print_meENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE in:
main.o
something.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1
Which makes sense to me, since util.h is included in main.cpp and something.cpp there are duplicate symbols, right?
Question, is it possible to be as lazy to have it all in the header? Or no way, have to split decalration and definition? I don't care (in this case) to hide the implementation in the .cpp, I just want to move it out of sth.
Maybe move the definition of print_me down to util.cpp and only leave a declaration of it in the util.h file.
Else you get a copy of it in every object file, and then the linker gets confused as they all have the same name (symbol).

Very basic: Why won't my makefile work with common suffix

objects = hello.o name.o printing.o
exename = himake
$(exename): $(objects)
$(CC) -o $(exename) $(objects)
%.o: %.cpp
$(CC) -c $^
I am trying to use common suffixes so I do not need to compile 3 files into .o first. This is supposed to do all three with the % wildcard.
It works fine when I do it the long way but not this.
Running the above makefile gives me this error below:
[alex#pcc Dir]$ make
cc -o himake hello.o name.o printing.o
hello.o: In function `__static_initialization_and_destruction_0(int, int)':
hello.cpp:(.text+0x23): undefined reference to `std::ios_base::Init::Init()'
hello.o: In function `__tcf_0':
hello.cpp:(.text+0x66): undefined reference to `std::ios_base::Init::~Init()'
and more that I did not include
Files:
hello.cpp:
// hello.cpp
// standard library
#include <iostream>
#include <string>
using namespace std;
// user defined header files
#include "name.h"
#include "printing.h"
int main ()
{
string name;
name = getName(); // getName is in name.h
printHello(name); // printHello is in print.h
return 0;
}
name.cpp
// name.cpp
// user defined header files
#include "name.h"
#include "printing.h"
string getName()
{
string name;
printGreeting(); // printGreeting is from print.h
getline(cin, name);
return name;
}
name.h
// name.h
#include <iostream>
using namespace std;
string getName();
printing.cpp
// printing.cpp
// user defined include files
#include "printing.h"
void printGreeting(void)
{
cout << "Your name: ";
return;
}
void printHello (string name)
{
cout << "Hi, " << name << endl;
return;
}
printing.h
// printing.h
#include <iostream>
using namespace std;
void printGreeting();
void printHello(string);
Because you use the C compiler frontend program, and not the C++ frontend program.
Change $(CC) to $(CXX).

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

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.