Undefined reference to 'operator delete(void*)

2020-06-08 14:37发布

问题:

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

回答1:

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.



回答2:

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++."



回答3:

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.



回答4:

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