【问题标题】:Undefined reference to 'operator delete(void*)'对“操作员删除(void *)”的未定义引用
【发布时间】:2011-10-24 07:46:01
【问题描述】:

我是 C++ 编程的新手,但从事 C 和 Java 方面的工作已经很长时间了。我正在尝试在我正在处理的一些串行协议中做一个类似接口的层次结构,并不断收到错误:

Undefined reference to 'operator delete(void*)'

(简化的)代码如下:

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();
}

构造函数和 nextByte 函数在 StringWriter.cpp 中实现,但仅此而已。我需要能够从指向 PacketWriter 的指针中删除 StringWriter,如果我为 StringWriter 定义了一个析构函数,无论是否虚拟,我都会遇到各种其他类似的错误。我确信这是一个我作为新手忽略的简单问题。

另外,我正在为 AVR 芯片编写此代码,在 Windows 上使用 avr-g++。

谢谢

【问题讨论】:

  • 如何运行编译器?如果你使用avr-gcc 或类似的东西,那么你应该使用avr-g++ 或类似的东西。
  • 你是否以一种特殊的方式链接这个?如果您链接到通常的运行时,则提供了 operator newoperator delete 的实现,但如果您做一些无鞍的事情,您可能需要自己定义这些。
  • 如果您没有将 C++ 标准库链接到最终的可执行文件中,则会出现此错误。你把这个链接进去了吗?
  • 我很确定 new/delete 没有被实现,并且有充分的理由,它是一个嵌入式系统。正确阅读文档。
  • @hexa:很好的收获:nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus。您可能可以将此作为答案发布

标签: c++ embedded destructor avr avr-gcc


【解决方案1】:

很抱歉在旧帖子中发帖,但它在 Google 的搜索结果中仍然很高,如果你有这个问题,你真的应该查看 this link,因为那里说你只需要链接 -lstdc++ 和这个是什么解决了我的问题。

社区添加了以下行,但并未将其突出显示,而是出于我无法理解的原因仅在我的答案中添加评论: “或者使用隐式添加 -lstdc++ 选项的 C++ 编译器,例如 g++。”

【讨论】:

  • 仅供参考。 stdc++ 中的链接不一定能解决此问题。我正在使用 -lstdc++ 并尝试了 g++,但仍然看到这个问题。
  • 我已经用头撞墙好几个星期了,现在试图弄清楚为什么我的 CUDA 代码不能正常运行。我尝试了所有可能找到的东西。你的评论解决了一切,挽救了一天,解决了我的生活,我非常爱你。谢谢谢谢谢谢谢谢!!!!!!
  • 确保 -lstdc++ 在“FWIW 之后”
  • 神奇地解决了我的问题。谢谢!供以后读者参考:我正在尝试从我的嵌入式 Linux C 代码链接一个名为 libzmq 的 C++ 库。如果我使用 C++ 编译器,一切都很好,但如果我出于某种原因必须使用 C 编译器。然后我看到所有那些未定义的错误。添加-lstdc++ 即可解决问题。
【解决方案2】:

如果您由于某种原因没有链接到标准库(在嵌入式场景中很可能就是这种情况),您必须提供自己的运算符newdelete。在最简单的情况下,您可以简单地包装 malloc,或者从您自己喜欢的来源分配内存:

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);
}

如果您正在为普通的托管平台进行编译,则永远不必这样做,因此,如果确实需要这样做,您最好熟悉平台上内存管理的复杂性。

【讨论】:

  • 这个芯片好像没有标准库支持:nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus。甚至记录了 OP 观察到的 new 和 delete 的行为。
  • 我知道 C 中的 AVR 有 malloc 和 free 的实现。如果我只是在某个地方将它们包装一次,它们是否适用于所有对象?我应该把那个代码放在哪里?
  • 您将代码放在全局命名空间中的任何位置并链接到它。如果你不想要malloc,你也可以从一些池区分配内存并维护一个空闲列表或类似的东西。
  • 好吧,这似乎可以工作(或者至少编译没有错误:P)。谢谢!
  • 很酷,但请注意,您真的必须知道自己在做什么以及从哪里获取记忆。我认为malloc 是嵌入式世界中非常危险的野兽,但我绝对不是专家。
【解决方案3】:

我只会引用文档,因为他们说得更好。

编写 C++

你可以用 C++ 为 AVR 平台编写程序,如果你包括 c++ 在配置 avr-gcc 期间启用的语言。只是 关于编写 C AVR 程序部分的所有内容都适用,所以 先读一下。

使用 C++ 的主要缺点是:

C++ calling convention side-effects
No libstdc++ support.

C++ 调用约定副作用

某些 C++ 功能将自动生成隐含代码,如果 需要,这会浪费宝贵的程序内存空间和处理器 时间。例如,如果在程序中的某个时刻,一个函数是 按值传递一个 C++ 对象:

void myfunction(MyCppClass object);

您最终会生成一个默认的复制构造函数,并且 调用以创建 myfunction() 中使用的对象的临时副本。是 如果这不是您想要的,请小心:等效行为应该是 可通过传递对常量 MyCppClass 对象的引用来实现, 同时避免代码和执行开销。

缺少 libstdc++ 和其他 C++ 功能

没有任何 C++ 标准模板、类或函数 可用的。此外,new 和 delete 操作符尚未 已实施。

C++ 异常支持也缺乏。你可能需要做 确保使用 -fno-exceptions 编译器选项来关闭 C++ 前端的异常。

什么有效?尽管你已经习惯了很多 C++ 好东西 无法使用,值得对 C++ 中的 AVR。构造函数和析构函数是函数式的,只是 使用类和面向对象的组织优势 编程可能会让 C++ 成为一个不错的选择。

【讨论】:

  • 我将补充说“未实现运算符 new 和 delete,尝试使用它们会导致链接器抱怨未定义的外部引用。(这可能会被修复。)”
【解决方案4】:

如果您只是想做一个界面,则不需要新建/删除。只需从基类析构函数中删除“虚拟”,并确保派生类具有 __cxa_pure_virtual()。

这是一个可编译的示例。 (为了简单起见,我删除了返回值,但它与它们配合得很好。)

在 PacketWriter.h 中

class PacketWriter {
public:
    virtual void nextByte() = 0;
protected:
    ~PacketWriter() {}
};

在 StringWriter.h 中

#include "PacketWriter.h"

class StringWriter : public PacketWriter {
public:
    StringWriter(const char* message);
    void nextByte();
};  

在 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()
{
}

avr-g++ StringWriter.cpp编译

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 2011-10-29
    相关资源
    最近更新 更多