G++ - Undefined Reference to member function that is defined - c++

I am currently working on a virtual run time environment program that is at a very early stage, i am prevented from continuing my work due to a linker error when using my makefile, provided below. The error i am receiving is:
g++ controller.o processor.o test.o -o final
controller.o: In function `Controller::run()':
controller.cpp:(.text+0x1e0): undefined reference to
Processor::codeParams(char)'
controller.o: In function `Controller::fetch()':
controller.cpp:(.text+0x290): undefined reference to `Controller::pc'
controller.cpp:(.text+0x299): undefined reference to `Controller::pc'
collect2: error: ld returned 1 exit status
makefile:16: recipe for target 'final' failed
make: *** [final] Error 1
I am unsure as to why i get this error as i thought i had defined these things in the source file corresponding to the header. All files will be given below so that the program can be compiled.
test.cpp:
#include <iostream>
#include <vector>
#include "includes/controller.h"
using namespace std;
int main()
{
vector<char> prog = {0x0};
Controller contr(prog);
cout << "Error Code: " << contr.run() << endl;
return 0;
}
controller.cpp:
/*
Author(s): James Dolan
File: controller.cpp
Build: 0.0.0
Header: includes/controller.h
DoLR: 21:39 11/1/2017
Todo: n/a
*/
#include "includes/controller.h"
Controller::Controller(vector<char> prog)
{
printf("Program:"); //Display program
for(auto i : program)
{
printf("%02X", i);
}
printf("\n");
Controller::program = program;
}
Controller::~Controller ()
{
}
int Controller::run()
{
bool runFlag = true;
int errorCode = 0;
char curCode;
vector<char> curInstr;
int paramRef;
while(runFlag)
{
curCode = fetch();
printf("curCode:%02X\n", curCode);
curInstr.push_back(curCode);
paramRef = proc.codeParams(curCode);
if (paramRef == 0xffff){runFlag = false; continue;} //Check if shutdown signal was returned, if so shutdown
printf("opcode good\n");
for(int i; i<paramRef; i++){curInstr.push_back(fetch());}
}
return errorCode;
}
char Controller::fetch()
{
return program[pc++]; //Return next instruction then increment the program counter
}
controller.h:
/*
Author(s): James Dolan
File: controller.h
Source: ../controller.cpp
DoLR: 21:39 11/1/2017
Todo: n/a
*/
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <iostream>
#include <vector>
#include <cstdlib>
#include "processor.h"
using namespace std;
class Controller{
public:
Controller(vector<char> prog);
~Controller();
int run();
protected:
private:
vector<char> program;
static int pc;
char fetch();
Processor proc();
};
#endif
processor.cpp:
#include "includes/processor.h"
Processor::Processor()
{
}
Processor::~Processor()
{
}
int codeParams(char code)
{
switch(code)
{
case 0x0: //Halt
return 0;
default:
printf("[ERROR!] Invalid opcode [%02X]", code);
return 0xffff; //Return shutdown signal
}
}
processor.h:
#ifndef PROCESSOR_H
#define PROCESSOR_H
#include <iostream>
#include <cstdlib>
class Processor{
public:
Processor();
~Processor();
int codeParams(char code);
protected:
private:
};
#endif
All if any help is appreciated massively as it will help me to continue with my passion of developing a fully fledged open-source virtual runtime enviroment like the java vm, thank you for your time.

In Controller.cpp you need a int Controller::pc; or int Controller::pc = 0;
In the header file you declared a static int named pc that exists somewhere. It needs to actually exist in a translation unit somewhere (in this case Controller.cpp) so that when the linker tries to find it... it exists.
In Processor.cpp your signature should look like int Processor::codeParams(char code) to let the compiler know that is Processor's codeParams and not a random function named codeParams that happens to also take a character.

For the member function Processor::codeParams you should define it as:
int Processor::codeParams(char code)
// ~~~~~~~~~~~
{
...
}
Otherwise it's just a normal (non–member) function.
For the static member Controller::pc you should define it outside of the class definition, in controller.cpp.
// Controller.h
class Controller {
...
private:
static int pc;
};
// controller.cpp
int Controller::pc;

Related

How am I supposed to declare this C++ function?

I have a C++ program with an undefined reference error on the call of a method in a class. As near as I can tell, the method is public and I'm calling it with a parameter declared the same as the method definition, but eclipse/gcc tells me it is undefined. I'm not used to C++, can someone please tell me what's wrong with the definition?
The main class:
#include <iostream>
using namespace std;
#include "AttenuationConfigurationTable.h"
int main()
{
flash_entry_struct flash_array[] = { { 10, 20, 30, 40 }, { 50, 60, 70, 80 }, { -1, -1, -1, -1 } };
// note: no undefined reference or any other error for the line with the class
AttenuationConfigurationTable attConfigTable;
// error appears for next line: undefined reference to ...load_attenuation_...
attConfigTable.load_attenuation_calibration_table_from_flash(flash_array);
return 0;
}
The class file:
#include "AttenuationConfigurationTable.h"
#include "flashEntryStruct.h"
AttenuationConfigurationTable::AttenuationConfigurationTable() { }
AttenuationConfigurationTable::~AttenuationConfigurationTable() { }
class Attenuation_configuration_table
{
struct attenuation_voltages_struct
{
float att_value;
float v1;
float v2;
} ;
struct frequency_tables_struct
{
int frequency;
attenuation_voltages_struct attenuation_voltages[100];
int voltages_count = 0;
} ;
frequency_tables_struct _frequency_tables[42];
public:
/************************************************************************/
/* load the table in this object from the given flash memory address */
/************************************************************************/
void load_attenuation_calibration_table_from_flash(flash_entry_struct memory_address[])
{
// bunch of logic here...
}
};
The h file for the class:
#ifndef ATTENUATIONCONFIGURATIONTABLE_H_
#define ATTENUATIONCONFIGURATIONTABLE_H_
#include "flashEntryStruct.h"
class AttenuationConfigurationTable
{
public:
AttenuationConfigurationTable();
virtual ~AttenuationConfigurationTable();
void load_attenuation_calibration_table_from_flash(flash_entry_struct flash_memory_address[]);
};
#endif /* ATTENUATIONCONFIGURATIONTABLE_H_ */
And, just for completeness, the h file defining the parameter structure:
#ifndef FLASHENTRYSTRUCT_H_
#define FLASHENTRYSTRUCT_H_
struct flash_entry_struct
{
uint16_t frequency;
uint16_t scaled_db;
int8_t v1_byte;
int8_t v2_byte;
} ;
#endif /* FLASHENTRYSTRUCT_H_ */
EDIT: the error message itself:
Invoking: Cygwin C++ Linker
g++ -o "HelloCPP.exe" ./src/AttenuationConfigurationTable.o ./src/Hello2.o ./src/HelloCPP.o
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: ./src/HelloCPP.o:/cygdrive/c/Users/ralph/files/programming/workspaces/HelloCPP/HelloCPP/Debug/../src/HelloCPP.cpp:15: undefined reference to `AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(flash_entry_struct*)'
collect2: error: ld returned 1 exit status
make: *** [makefile:58: HelloCPP.exe] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
You declare AttenuationConfigurationTable in the header file with the load_attenuation_calibration_table_from_flash function, but then the function with the same name in the implementation file is inside the definition for another class, Attenuation_configuration_table.
Take the implementation for load_attenuation_calibration_table_from_flash out of the class definition for Attenuation_configuration_table in your cpp file, and define it instead as
void AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(/* ... */) {
// ...
}
This is the same syntax already used for the constructor and destructor in that file.
In the end, your header should look something like this:
class AttenuationConfigurationTable
{
public:
AttenuationConfigurationTable();
virtual ~AttenuationConfigurationTable();
void load_attenuation_calibration_table_from_flash(flash_entry_struct flash_memory_address[]);
private:
struct attenuation_voltages_struct
{
float att_value;
float v1;
float v2;
} ;
struct frequency_tables_struct
{
int frequency;
attenuation_voltages_struct attenuation_voltages[100];
int voltages_count;
} ;
frequency_tables_struct _frequency_tables[42];
};
and your cpp file should look something like this:
AttenuationConfigurationTable::AttenuationConfigurationTable() { }
AttenuationConfigurationTable::~AttenuationConfigurationTable() { }
void AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(/* params */) {
// body
}

Why can't the linker find this destructor on Ubuntu

There is a console application, I write it as part of self-improvement. Sometimes I write in Windows, sometimes in Ubuntu. Until some time there was no problem. Suddenly now with the following settings on Ubuntu, when running:
g++ AlarmSystem.cpp -o main, I get this type of error:
/usr/bin/ld: /tmp/cchydRcW.o: in function `main': AlarmSystem.cpp:(.text+0x43): undefined reference to `MainConsoleController::MainConsoleController()'
/usr/bin/ld: AlarmSystem.cpp:(.text+0x57): undefined reference to `MainConsoleController::~MainConsoleController()'
collect2: error: ld
returned 1 exit status
AlarmSystem.cpp
#include "MainConsoleController.h"
int main()
{
MainConsoleController m = MainConsoleController();
return 0;
}
MainConsoleController.h
#pragma once
#ifndef MAIN_CONSOLE_CONTROLLER_H
#define MAIN_CONSOLE_CONTROLLER_H
#include <iostream>
#include "MainConsoleView.h"
#include "MainConsole.h"
class MainConsoleController
{
private:
std::string _currentCommand;
Commands _command;
MainConsoleView _view;
MainConsole _model;
bool _isWorking;
public:
MainConsoleController();
virtual ~MainConsoleController();
void CheckInput();
void MainLoop();
void ConvertInput();
void MakeCommand();
};
#endif
MainConsoleController.cpp
#include "MainConsoleController.h"
MainConsoleController::MainConsoleController()
{
this->_isWorking = true;
MainLoop();
}
MainConsoleController::~MainConsoleController()
{
}
void MainConsoleController::CheckInput()
{
std::cin >> this->_currentCommand;
}
void MainConsoleController::MainLoop()
{
this->_view.PrintWelcome();
while (this->_isWorking)
{
CheckInput();
ConvertInput();
MakeCommand();
}
}
...
Can anyone tell me what the problem is?

undefined reference to pthread create even with lpthread [duplicate]

This question already has answers here:
Difference between -pthread and -lpthread while compiling
(3 answers)
Closed 4 years ago.
I want to make use of pthread ad hence use the -lpthread flag to compile, but here's what I get:
$ g++ -lpthread pseudo_code.cpp
/tmp/cc3mPrvt.o: In function `MyThreadClass::StartInternalThread()':
pseudo_code.cpp:(.text._ZN13MyThreadClass19StartInternalThreadEv[_ZN13MyThreadClass19StartInternalThreadEv]+0x26): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
The code I try to compile is below:
#include <pthread.h>
#include <iostream>
#include <vector>
#define OK 0
#define ERROR -1
//-- ThreadClass
class MyThreadClass
{
public:
MyThreadClass() {/* empty */}
virtual ~MyThreadClass() {/* empty */}
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool StartInternalThread()
{
return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
}
/** Will not return until the internal thread has exited. */
void WaitForInternalThreadToExit()
{
(void) pthread_join(_thread, NULL);
}
protected:
/** Implement this method in your subclass with the code you want your thread to run. */
virtual void InternalThreadEntry() = 0;
private:
static void * InternalThreadEntryFunc(void * This) {
((MyThreadClass *)This)->InternalThreadEntry(); return NULL;
}
pthread_t _thread;
};
//-- /ThreadClass
//--- DUMMY DECLARATIONS BELOW TO MAKE IT COMPILE ---//
#define LOG_NS_ERROR std::cout
class test{
public:
int get_child(std::string x){return OK;};
};
test *_global;
typedef struct test_struct{} _db_transact;
class db_transact{
public:
db_transact(int,int&,int&){};
};
int _ns;
int _log_id;
//--- DUMMY DECLARATIONS ABOVE TO MAKE IT COMPILE ---//
class db_c_hndlr : public MyThreadClass{
public:
db_c_hndlr(void);
~db_c_hndlr(void);
db_transact *db_conn_get(void);
void InternalThreadEntry(void *func);
private:
int _stop;
std::vector<db_transact*> _db_pool;
};
//---------------------------------------------------------
db_c_hndlr::db_c_hndlr(void) {
}
//---------------------------------------------------------
void db_c_hndlr::InternatThreadEntry(void *func) {
while(!stop){
std::cout << "going!" << std::endl;
sleep(1);
}
}
//---------------------------------------------------------
db_c_hndlr::~db_c_hndlr() {
int i = 0;
std::vector<db_transact*>::iterator it;
for (i=0, it = _db_pool.begin();it!=_db_pool.end();it++, i++) {
if (_db_pool[i])
if (_db_pool[i]!=NULL)
delete _db_pool[i];
}
}
//---------------------------------------------------------
db_transact *db_c_hndlr::db_conn_get(void) {
db_transact *tmp;
tmp = new db_transact(_global->get_child("db_config"), _ns, _log_id);
_db_pool.push_back(tmp);
return tmp;
}
//---------------------------------------------------------
int main(void)
{
db_transact *conn=NULL;
db_c_hndlr db;
//db = new db_c_hndlr();
conn= db.db_conn_get();
return OK;
}
Probably you need to do this:
extern "C" {
#include <pthread.h>
}
That tells the compiler that this header is for a C library, and that it should not use C++ name mangling.
You also need to use -pthread instead of -lpthread, because the pthread library is special and GCC wants to explicitly know you are trying to use threads, not simply link against libpthread.
Please try to compile with the command.
g++ pseudo_code.cpp -lpthread
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, foo.o -lz bar.o searches library z after
file foo.o but before bar.o. If bar.o refers to functions in z, those
functions may not be loaded.
It worked for me. It seems, needs to specify the library after the source file so that symbols are searched in the library.

g++7 compile error when member function name as errno and cerrno included

main.cc
#include <cerrno>
class A {
public:
int errno();
};
int A::errno()
{
return 0;
}
int main()
{
return 0;
}
compile main.cc with g++ report error:
In file included from /usr/include/c++/7/cerrno:42:0,
from 1.cc:1:
main.cc:8:8: error: expected unqualified-id before ‘(’ token
int A::errno()
But the same code compile successfully by g++6 and below
And the following code compile successfully by g++7
#include <cerrno>
class A {
public:
int errno()
{
return 0;
}
};
int main()
{
return 0;
}
So any ideas?
errno is a macro.
Quoting cppreference
macro which expands to POSIX-compatible thread-local error number variable
if you add an #undef errno in your sources it will compile but somehow defeats the purpose of errno.
You simply should not name a method errno.
To figure out why it works in one case and not in the other you need to expand the errno macro and see what was generated.
So here is the output or what the compiler tries to compile:
class A {
public:
int (*__errno_location ())(){return 0;}
};
class A {
public:
int(*foo()) ();
};
int A::(*__errno_location ())(){return 0;}

Multiple definition error of base class constructor while compiling

I'm coding a spreadsheet built up of column vectors and cell vectors, where
each cell is a placeholder for a cell value. CellValueBase is the base class, CellValue is the final template class.
This is the error:
g++ Cell.o Column.o sheet.o main.o -o spreadsheet
sheet.o: In function `CellValueBase::CellValueBase()':
sheet.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
sheet.o: In function `CellValueBase::CellValueBase()':
sheet.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
main.o: In function `CellValueBase::CellValueBase()':
main.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
main.o: In function `CellValueBase::CellValueBase()':
main.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
Cell.o: In function `CellValueBase::~CellValueBase()':
Cell.cc:(.text._ZN13CellValueBaseD2Ev[_ZN13CellValueBaseD5Ev]+0xd): undefined reference to `vtable for CellValueBase'
Cell.o: In function `CellValueBase::CellValueBase()':
Cell.cc:(.text._ZN13CellValueBaseC2Ev[_ZN13CellValueBaseC5Ev]+0x9): undefined reference to `vtable for CellValueBase'
Cell.o:(.rodata._ZTI9CellValueIfE[_ZTI9CellValueIfE]+0x10): undefined reference to `typeinfo for CellValueBase'
Column.o: In function `CellValueBase::CellValueBase()':
Column.cc:(.text+0x9): undefined reference to `vtable for CellValueBase'
sheet.o: In function `CellValueBase::CellValueBase()':
sheet.cc:(.text+0x9): undefined reference to `vtable for CellValueBase'
main.o: In function `CellValueBase::CellValueBase()':
main.cc:(.text+0x9): undefined reference to `vtable for CellValueBase'
collect2: error: ld returned 1 exit status
Makefile:8: recipe for target 'Spreadsheet' failed
make: *** [Spreadsheet] Error 1
And this is my code:
main.cc
#include <iostream>
#include "sheet.h"
using namespace std;
int main () {
Sheet *sht;
sht = new Sheet ();
return 0;
}//main
sheet.h
#ifndef SHEET_H
#define SHEET_H
#include "Column.h"
// Vaste grootte van de sheet
const int AantReg = 24;
const int AantKol = 80;
class Sheet
{
public:
Sheet ();
void getCell();
void begin();
void end();
private:
std::vector<Column*> sheetCol;//bevat de columns
int regels, kolommen;
};
#endif
sheet.cc
#include <iostream>
#include "sheet.h"
using namespace std;
Sheet::Sheet () {
regels = AantReg;
kolommen = AantKol;
cout << "Kolommen" << endl;
for (int i = 0; i < kolommen; i++) {
cout << "kolomnr: " << i << endl;
sheetCol.push_back(new Column(regels));
}
cout << endl << endl;
}
void Sheet::getCell () {
//TODO: fixen
}
void Sheet::begin () {
//TODO: deze shit ook fixen
}
void Sheet::end () {
}
Column.h
#include <vector>
#include "Cell.h"
class Column
{
public:
Column (int n);
//void getCell();
//void begin();
//void end();
private:
int aantCellen;
std::vector<Cell*> columnVec;//sla je de cellen in op
};
#endif
Column.cc
#include <iostream>
#include "Column.h"
using namespace std;
Column::Column(int n): aantCellen(n)
{
for (int i = 0; i < aantCellen; i++) {
cout << "celnr: " << i << endl;
columnVec.push_back(new Cell());
}
}//cell
Cell.h
#ifndef CELL_H
#define CELL_H
#include "CellValueBase.h"
#include <string>
#include <memory>
class Cell {
public:
Cell();
void setValueFloat(float newValue);
//void setValueInt(int newValue);
//void setValueString(std::string newValue);
//void setValueFormula(std::string newValue);
//std::unique_ptr<cellValueBase> readValue();
void emptyCell();
private:
std::unique_ptr<CellValueBase> value;
};
#endif
Cell.cc
#include "Cell.h"
#include <iostream>
using namespace std;
Cell::Cell() {
value.reset(nullptr);
cout << "hallo wereld ik ben een cel" << endl;
setValueFloat(3.14);
} // Cell
void Cell::setValueFloat(float newValue)
{
value = unique_ptr<CellValueBase>(new CellValue<float>(newValue));
value->returnValueNumber();
} // setValueFloat
CellValueBase.h
#ifndef CELLVALUEBASE_H
#define CELLVALUEBASE_H
#include <iostream>
#include <string>
#include <sstream>
#include <stdexcept>
class CellValueBase
{
public:
CellValueBase();
virtual ~CellValueBase() {};
//virtual std::string returnValueStringEdit() = 0;
virtual float returnValueNumber();
void emptyCell();
private:
};
CellValueBase::CellValueBase()
{
} // CellValueBase
template<typename T>
class CellValue final : public CellValueBase
{
public:
CellValue(T initial_value)
: CellValueBase(), value(initial_value)
{ }
~CellValue();
//std::string returnValueString();
//std::string returnValueStringEdit();
float returnValueNumber();
private:
T value;
};
template<typename T>
CellValue<T>::~CellValue()
{
// TODO
}
template<typename T>
float CellValue<T>::returnValueNumber() {
return value;
}
And the makefile:
CC = g++
CompileParms = -c -std=c++14 -Wall -Wextra
OBJS = Cell.o Column.o sheet.o main.o
Spreadsheet: $(OBJS)
$(CC) $(OBJS) -o spreadsheet
Cell.o: Cell.cc CellValueBase.h Cell.h
$(CC) $(CompileParms) Cell.cc
Column.o: Column.cc Column.h
$(CC) $(CompileParms) Column.cc
sheet.o: sheet.cc sheet.h
$(CC) $(CompileParms) sheet.cc
main.o: main.cc sheet.h
$(CC) $(CompileParms) main.cc
You have correctly understood that templates needs to be defined in their header file. But the class CellValueBase is not a template, so the definition of the CellValueBase constructor in the header file is incorrect. It means the constructor will be defined everywhere the header file is included.
The simple solution? Define the CellValueBase constructor inline in the class (like you already do with the destructor).
Furthermore, all virtual but non-abstract functions in a class must have a definition. So either make CellValueBase::returnValueNumber abstract or have an empty definition.
All in all, the CellValueBase class could look like this:
class CellValueBase
{
public:
CellValueBase() {} // <- Define inline
virtual ~CellValueBase() {};
//virtual std::string returnValueStringEdit() = 0;
virtual float returnValueNumber() = 0; // <- Declare abstract
void emptyCell();
private:
};
Look at CellValueBase.h. You can not define non-inline class methods outside of the class in header files. You must define them in .cpp files.
Move this method's definition to to CellValueBase.cpp:
CellValueBase::CellValueBase()
{
} // CellValueBase
Define non-inline methods or functions in header is totally bad practice. Error appears not at once, it appears only when you include this header in two cpp files. It means that linker founds two same methods definitions and that is the problem. If you would leave definition in your header CellValueBase.h and include CellValueBase.h once in .cpp file then there won't be any problems. But when you include CellValueBase.h more than once then linker founds duplicate definition.
But even if you know that you won't include header file with non-inline methods definitions more then once then you also should remember never to define non-inline functions or class methods outside classes. You can forget about your "1 include rule" for this file and later include it twice and linker will detect duplicate definition.
Also you can define template methods without specialization or define inline specialized template methods in header files.