I'm new to C++ programming, but have been working in C and Java for a long time. I'm trying to do an interface-like hierarchy in some serial protocol I'm working on, and keep getting the error:
Undefined reference to 'operator delete(void*)'
The (simplified) code follows below:
PacketWriter.h:
class PacketWriter {
public:
virtual ~PacketWriter() {}
virtual uint8_t nextByte() = 0;
}
StringWriter.h:
class StringWriter : public PacketWriter {
public:
StringWriter(const char* message);
virtual uint8_t nextByte();
}
The constructor and nextByte functions are implemented in StringWriter.cpp, but nothing else. I need to be able to delete a StringWriter from a pointer to a PacketWriter, and i've been getting various other similar errors if I define a destructor for StringWriter, virtual or not. I'm sure it's a simple issue that I'm overlooking as a newbie.
Also, I'm writing this for an AVR chip, using avr-g++ on Windows.
Thanks
If you are not linking against the standard library for some reason (as may well be the case in an embedded scenario), you have to provide your own operators new
and delete
. In the simplest case, you could simply wrap malloc
, or allocate memory from your own favourite source:
void * operator new(std::size_t n)
{
void * const p = std::malloc(n);
// handle p == 0
return p;
}
void operator delete(void * p) // or delete(void *, std::size_t)
{
std::free(p);
}
You should never have to do this if you are compiling for an ordinary, hosted platform, so if you do need to do this, you better be familiar with the intricacies of memory management on your platform.
Sorry for posting in an old thread, but it's still pretty high in Google's search results and if you have this problem, you really should check out this link, because there it says that you simply need to link -lstdc++ and this is what solved the problem for me.
The following line was added by the Community without highlighting it as such and instead of just adding a comment to my answer for reasons that elude me:
"Or use a C++ compiler that will implicitly add the -lstdc++ option, e.g. g++."
I will just quote the documentation, since they put it better.
Writing C++
You can write programs for the AVR platform in C++, if you included
c++ in the enabled-languages during configuration of avr-gcc. Just
about everything in the Writing C AVR programs section applies, so
read that first.
The major drawbacks of using C++ are:
C++ calling convention side-effects
No libstdc++ support.
C++ calling convention side-effects
Certain C++ features will automatically generate implied code if
required, which can waste valuable program memory space and processor
time. For instance, if at some point in the program a function is
passed a C++ object by value:
void myfunction(MyCppClass object);
You will wind up with a default copy constructor being generated and
called to create the temporary copy of object used in myfunction(). Be
careful if this isn't what you want: equivalent behavior should be
attainable by passing a reference to a constant MyCppClass object,
while avoiding the code and execution overhead.
Missing libstdc++ and other C++ features
None of the C++ standard templates, classes or functions are
available. In addition, operators new and delete have yet to be
implemented.
C++ exception support is also lacking. You'll probably need to make
sure to use the -fno-exceptions compiler option to turn off the
exceptions in the C++ front-end.
What does work? Even though lots of the C++ goodies you are accustomed
to working with aren't available, it can be worthwhile to program the
AVR in C++. Constructors and destructors are functional and just the
organizational advantages of using classes and object oriented
programming may make C++ a great choice.
If you're just looking to do an interface, you don't need new/delete. Just remove the "virtual" from the base class destructor, and make sure the derived class has an implementation of
__cxa_pure_virtual().
Here is a compilable example. (I removed the returns to keep things simple, but it works just fine with them.)
In PacketWriter.h
class PacketWriter {
public:
virtual void nextByte() = 0;
protected:
~PacketWriter() {}
};
In StringWriter.h
#include "PacketWriter.h"
class StringWriter : public PacketWriter {
public:
StringWriter(const char* message);
void nextByte();
};
In StringWriter.cpp
#include "StringWriter.h"
// Definition of the error function to call if the constructor goes bonkers
extern "C" void __cxa_pure_virtual() { while (1); }
StringWriter::StringWriter(const char* message)
{
// constructor code here
}
void StringWriter::nextByte()
{
}
Compile with avr-g++ StringWriter.cpp