web-dev-qa-db-ja.com

'operator delete(void *)'への未定義の参照

私は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のデストラクタを定義すると、他のさまざまな同様のエラーが発生します。初心者として見落としているのは簡単な問題だと思います。

また、Windowsでavr-g ++を使用して、AVRチップ用にこれを書いています。

ありがとう

15
Bracket

何らかの理由で(組み込みシナリオの場合のように)標準ライブラリにリンクしない場合は、独自の演算子newおよびdeleteを提供する必要があります。最も単純なケースでは、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);
}

通常のホストされたプラットフォーム用にコンパイルする場合は、これを行う必要はありません。そのため、これを行う必要がある場合は、プラットフォームでの複雑なメモリ管理に精通している必要があります。

14
Kerrek SB

古いスレッドに投稿して申し訳ありませんが、それでもGoogleの検索結果ではかなり高いので、この問題が発生した場合は、実際に確認する必要があります this link 。 lstdc ++そしてこれが私にとって問題を解決したものです。

次の行は、それ自体を強調せずに、コミュニティーによって追加されたものであり、理由がわからないために私の回答にコメントを追加するだけではありません。

25
Alex

彼らはそれをよりよく置くので、私はドキュメントを引用します。

C++の記述

Avr-gccの構成中に有効言語にc ++を含めた場合、C++でAVRプラットフォーム用のプログラムを作成できます。 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++を優れた選択肢にするかもしれません。

9

インターフェースを実行したいだけの場合は、new/deleteは必要ありません。基本クラスのデストラクタから「仮想」を削除し、派生クラスに__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でコンパイル

4
MikeTwo