I think it's important to note that this compiles fine on Visual Studio 2012, but not in g++. It evened compiled fine at one point before I implemented RSA.cpp. I haven't touched the header files since. The error is:
cipher.o: In function `RSA_433::RSA_433()':
/home/andrew/Desktop/ciphers/RSA.h:18 undefined reference to `vtable for RSA_433'
collect2: error: ld returned 1 exit status
Here's RSA.h:
class RSA_433: public CipherInterface
{
public:
RSA_433(){}
virtual bool setKey(const unsigned char* key);
virtual unsigned char* encrypt(const unsigned char* plaintext);
virtual unsigned char* decrypt(const unsigned char* ciphertext);
protected:
RSA* RSAkey;
const char* keyFileName;
};
and RSA.cpp:
//RSA_433::RSA_433(){} removed
bool RSA_433::setKey(const unsigned char* key){//body}
unsigned char* RSA_433::encrypt(const unsigned char* plaintext){//body}
unsigned char* RSA_433::decrypt(const unsigned char* ciphertext){//body}
RSA.h also inherits from:
class CipherInterface
{
public:
CipherInterface(){}
virtual bool setKey(const unsigned char* key){ return false; }
virtual unsigned char* encrypt(const unsigned char* plaintext){ return NULL; }
virtual unsigned char* decrypt(const unsigned char* ciphertext) { return NULL; }
};
You seem to have two definitions for RSA_433::RSA_433(). One in the .h file and one in the .cpp file
Also, all the methods defined in class CipherInterface are inline. According to GCC standard,
The ISO C++ Standard specifies that all virtual methods of a class
that are not pure-virtual must be defined, but does not require any
diagnostic for violations of this rule [class.virtual]/8. Based on
this assumption, GCC will only emit the implicitly defined
constructors, the assignment operator, the destructor and the virtual
table of a class in the translation unit that defines its first such
non-inline method
That means GCC will only include vftable in the object file for the translation unit where the definition of the first non-pure, and non-inline virtual member function is present. If there is no such definition, vftable will not be included for the class.
The answer is simple: You should add and implement a virtual destructor in CipherInterface and the problem will go away.
Related
I'm trying to make a string class that can convert automatically to and from std::string.
class MyString
{
MyString(const std::string)
{
...
}
};
The issue is different compilers can have different layouts of std::string (e.g. Visual Studio 2010 vs 2015). So this constructor or autocast operator must be a function local to each compilation unit, AKA a static function. But you can't simply declare the member as static because the meaning isn't the same.
I know a guaranteed solution is to use a non-member function to do conversions and declare that as static. But would really appreciate a member function.
static MyString StringToMyString(const std::string& s);
I've considered forced inlining (even when optimizations are off), symbol aliasing, and symbol versioning and found forced inlining to be the simplest and most portable. __attribute__((alias)), requires the mangled C++ name and symbol versioning only works for shared libs and requires dynamic linker support. Here's an example that has 2 layouts for class My.
#include <stdio.h>
#define NO_INLINE __attribute__((noinline))
#define FORCE_INLINE __attribute__((always_inline))
class My
{
public:
FORCE_INLINE My(const String& s)
{
printf("creating from %s size=%d\n",s.s,(int)sizeof(s));
Construct(s.s);
}
NO_INLINE void Construct(const char* s)
{
printf("Construct(%s)\n",s);
}
};
void LibFunction();
#ifdef CLIENT
int main(int argc,char**argv)
{
String s;
s.s="string1";
My my(s);
LibFunction();
return 0;
}
#else
void LibFunction()
{
String s;
s.s="string2";
My my(s);
}
#endif
The output is this and is the same with or without optimizations
creating from string1 size=48
Construct(string1)
creating from string2 size=8
Construct(string2)
I've also investigated how QT deals with multiple layouts. In version 3.3, https://doc.qt.io/archives/3.3/qstring-h.html, it doesn't seem to:
class Q_EXPORT QString
{
QString( const std::string& );
};
Now, it's no longer a member function, but a private function to each compilation unit, presumably to allow multiple string layouts
class Q_CORE_EXPORT QString
{
static inline QString fromStdString(const std::string &s);
};
I have defined my own class in a Qt project that gives me problems, but I think this could be general C++.
When I try to declare a pointer to my class in any include file in the project myHashMap like
myHashMap* map;
the compiler gives the error and say "multiple definition of map". What is this? I didn't even define a pointer even, just declared one.
However, putting myHashMap* map in a source file doesn't give any errors.
Here is the class definition and declaration, sorry that it looks a bit messy.
#include QObject
#include QHash
class myHashMap : public QObject
{
Q_OBJECT
public:
explicit myHashMap(QObject *parent = 0);
float Get(const QString& key) const;
void setValue(const char key, float value)
{
// only emit value changed if the value has actually changed
//if( hash->value(key) != value)
//{
hash->insert(key,value);
//emit ValueChanged(key, value);
//}
}
signals:
public slots:
//void ValueChanged(const char& key, float newValue);
private:
QHash<const char, float>* hash;
};
myHashMap::myHashMap(QObject *parent) :
QObject(parent)
{
hash = new QHash<const char,float>;
}
EDIT:
Aaa, bummer, I just forgot to prepend MyHashMap* with the extern keyword. Programming C++ is a nitty-gritty. Wouldn't it make sense if the compiler sent a warning here, like "hello there, you now got multiple definitions in a few headers, forgot an extern keyword?" ?
However, I got a new problem.
In "communication.h" I have declared a namespace like this
namespace reference
{
extern const char potentiometer;
extern const char KpAngle;
extern const char KiAngle;
extern const char KdAngle;
extern const int length;
extern myHashMap* hmap;
void init();
}
In the communication.cpp I want to use *hmap like below, but the compiler returns "undefined reference to hmap". Yet I have included the "communication.h" both in "communication.cpp" and in the *.pro file. See the code below:
#include "communication.h"
namespace reference
{
const char potentiometer = 0x05;
const char KpAngle = 0x06;
const char KiAngle = 0x07;
const char KdAngle = 0x08;
const int length =1;
//QList<const char>* summary = new QList<const char>();
void init()
{
//using namespace reference;
//#include "communication.h"
//myHashMap* hmap = new myHashMap();
//when using this a hmap is created, however setValue returns undefined ref
//Both methods below returns "undefine reference to hmap". Same if i try "using namespace"
//reference::hmap = new myHashMap();
//hmap = new myHashMap();
/*
reference::hmap->setValue(potentiometer,-1);
reference::hmap->setValue(KpAngle,-1);
reference::hmap->setValue(KiAngle,-1);
reference::hmap->setValue(KdAngle,-1);*/
}
}
EDIT: Above a pointer to hmap is only declared, not defined. I therefore had do define hmap by putting
myHashMap* hmap directly in the reference scope in "communication.cpp". Now it works.
Prefix the declaration with extern in your header file; i.e.:
extern myHashMap* map;
You will also need to put the variable definition (without extern) into a source file somewhere.
The reason this causes a problem is because header files are typically included by multiple source files. Each source file is compiled in its own translation unit, independently of all the other ones. If you put a variable declaration in a header file, then you'll get multiple translation units all trying to define the same variable, causing a conflict.
What you want is for the variable to exist only within a single translation unit, hence the declaration in one source file. The extern version just indicates that there is (or will be) a variable with that name and type, but it doesn't actually cause it to be created. It effectively just makes it visible to anything which sees it.
It is likely that the name "map" is already reserved by another variable or function in a library you are using.Also if you include the header in other headers that are all included in your main file you can get this error.
I've been searching for a while and have found a lot of threads/pages that involve the problem I have, but I am not able to find
An explanation of why this error occurs
A working solution for my specific case
The following is Scanner.h:
class BaseReader {
public:
virtual ~BaseReader();
virtual const char* read() = 0;
virtual long position() = 0;
virtual long size() = 0;
virtual void seek(long position) = 0;
};
class CharReader : public BaseReader {
public:
CharReader(const char* source);
CharReader(const char* source, long size);
~CharReader();
const char* read();
long position();
long size();
void seek(long position);
private:
char* _source;
long _position;
long _size;
};
In Scanner.cpp I simply implement one of the constructors of CharReader.
I use Code::Blocks, but compiling it by myself results in the exact same problem.
niklas#emerald:~/git/hiterator (CPP)$ g++ main.cpp hiterator/Scanner.cpp -o main
/tmp/cclNNwgl.o: In function `hiterator::CharReader::CharReader(char const*)':
Scanner.cpp:(.text+0x16): undefined reference to `vtable for hiterator::CharReader'
collect2: ld gab 1 als Ende-Status zurück
#qdii:
#include "Scanner.h"
using namespace hiterator;
#include <stdlib.h>
#include <string.h>
CharReader::CharReader(const char* source) {
_size = strlen(source);
_source = (char*) malloc(_size + 1);
memcpy(_source, source, _size + 1);
}
Your program is incorrect. All virtual functions are considered used (odr-used) and thus you need to provide the definitions for all of them. Once you fix that, the issue should go away.
The compiler is complaining that the vtable is not available. Vtable-s are an implementation detail, and thus not treated by the standard, but many compilers will generate the vtable in the translation unit that defines the first (non-inline) virtual function. In your case, whatever the criterion to generate the vtable is, you are not complying with it.
See what I wrote on the GCC wiki to explain undefined reference to vtable for X errors.
There are also loads of existing questions on SO about that linker error, I'm sure one of them has an answer that explains it, e.g. here or here
You declared, but didn’t define, the virtual destructor in BaseReader. You need to provide a definition for this in the .cpp file in order for the vtable for BaseReader to be generated. Same for CharReader.
gsoap with its tools wsdl2h and soapcpp2 provided me with a soapStub.h file containing the following:
class SOAP_CMAC ns2__SOAPKunden
{
public:
std::string *adresszusatz;
// ...
public:
virtual int soap_type() const { return 7; }
// ...
ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { } // left out all member init.
virtual ~ns2__SOAPKunden() { }
};
I start with a small app using the class to populate objects with data from informix DB.
But to compile successfully i have to leave away all the virtual stuff - i found many postings about this error and use of virtual members in subclasses - otherwise i get
main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status
I admit after years of scripting only it's very hard for me to make sense of C++ code... I want to ask for any advice what to try next. My class is no derived class, is for example what makes me wonder.
The error means that the virtual table has not been correctly compiled/linked in the final binary (executable or library). There are two common circumstances that lead to this error:
you are not linking the object file that includes the virtual table definitions --i.e. you compiled soapStub.cpp into soapStub.o, but did not add that binary to the linker command line.
the compiler is not generating the virtual table anywhere, so even if you are including all object files, that does not include the virtual table.
The second case is the hardest to identify for non-experienced developers, and can be caused by a class that is defined in the header and contains virtual functions. If all the virtual functions are defined inlined, the compiler will generate the virtual table in all translation units that include the header, and mark it as a weak symbol so that the linker can discard them, but if you later add a new virtual method and you leave it undefined in the header --or if you remove the definition from one of the virtual functions--, then the compiler will not generate the virtual table in each translation unit, but only in the one that defines those functions.
Things to check:
you are linking all object files
either all virtual functions are defined inline in the class definition or you have a .cpp that defines the virtual functions and you are linking that in.
This is what David Rodriguez said, just stated simpler I guess...
I had this situation in my interface class:
class IBase
{
public:
virtual void begin(unsigned long);
virtual void end();
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
}
and changed it to this:
class IBase
{
public:
virtual void begin(unsigned long) = 0;
virtual void end() = 0;
virtual int available(void) = 0;
virtual int peek(void) = 0;
virtual int read(void) = 0;
virtual void flush(void) = 0;
}
which did the trick.
begin() and end() were defined in derived class in a different file, IBase class (interface) was only declared in header and included in few places.
Error from OP only appeared when I set optimizations to none (-O0), any other setting resulted in no error (gcc 4.8).
I'm getting some errors when compiling my program. They relate to the constructor and destructor of my class Instruction.
Errors are:
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x241): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::Instruction(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)':
ale.c:(.text+0x2ab): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x315): undefined reference to `vtable for Instruction'
/tmp/ccSWO7VW.o: In function `Instruction::~Instruction()':
ale.c:(.text+0x38d): undefined reference to `vtable for Instruction'
collect2: ld returned 1 exit status
Here is my code:
//classses.h
#include <iostream>
#include <string>
using namespace std;
class Instruction{
protected:
string name;
int value;
public:
Instruction(string _name, int _value);
~Instruction();
void setName(string _name);
void setValue(int _value);
string getName();
int getValue();
virtual void execute();
};
//constructor
Instruction::Instruction(string _name, int _value){
name = _name;
value = _value;
}
//destructor
Instruction::~Instruction(){
name = "";
value = 0;
}
void Instruction::setName(string _name){
name = _name;
}
void Instruction::setValue(int _value){
value = _value;
}
string Instruction::getName(){
return name;
}
int Instruction::getValue(){
return value;
}
/////////////////////////////////////////////////////////////////////
//ale.cpp
#include "headers.h"
#include "functions.h"
#include "classes.h"
#include <list>
using namespace std;
int main(){
return 0;
}
I would guess the problem is due to you declaring a virtual method 'execute' in the Instruction class, and never defining it anywhere. Compilers have to produce a vtable object for a class with virtual methods and really only want one copy of it, so they usually just do it in the compilation unit (source file) that defines the first virtual function...
You did not define your virtual function and/or g++ wants you to make your destructor virtual (because you have virtual functions which assumes inheritance)
Try
virtual void execute()=0;
This will make your class abstract, which seems to be what you intend since execute isn't defined.
If you ever want to use Instruction in more than one .cpp file, you should move the implementation of the class methods into a classes.cpp file.
As people already told, the problem is having execute() that is not implemented. Implement it, or make it pure virtual as says Dan Hook.
Just an extra remark: in many (maybe most depending on what you're coding on) cases, you don't need to implement the destructor. You just need if you want some specific functionnality (flushing data to a file for example).
As long as you have no pointer (as it is the case in your code), you won't have any memory tracking issues. Just remove the destructors: it's safe and it's less code.
However, if only one member is a pointer, then everything gets messy and you have to deal with memory management issues, memory leaks and segfaults ;)