Неопределенная ссылка на 'оператор 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, но ничего больше. Мне нужно удалить StringWriter из указателя на PacketWriter, и я получаю различные другие похожие ошибки, если я определяю деструктор для StringWriter, виртуальный или нет. Я уверен, что это простая проблема, которую я не замечаю как новичок.

Кроме того, я пишу это для микросхемы AVR, используя avr-g ++ в Windows.

Спасибо


person Bracket    schedule 10.08.2011    source источник
comment
Как запустить компилятор? Если вы используете avr-gcc или что-то в этом роде, вам лучше использовать avr-g++ или аналогичный.   -  person Alexandre C.    schedule 10.08.2011
comment
Вы уверены, что ошибка связана с кодом, который вы здесь показываете?   -  person sth    schedule 10.08.2011
comment
Вы каким-то образом связываете это? Если вы ссылаетесь на обычную среду выполнения, предоставляются реализации operator new и operator delete, но если вы делаете что-то без поддержки, вам может потребоваться определить их самостоятельно.   -  person Kerrek SB    schedule 10.08.2011
comment
Эта ошибка могла бы возникнуть, если бы вы не связали стандартные библиотеки C ++ с окончательным исполняемым файлом. Вы связываете это?   -  person templatetypedef    schedule 10.08.2011
comment
Мы не телепаты. Дайте нам код, который мы можем скомпилировать и получить те же результаты (ошибку), что и вы. Тогда мы сможем сказать вам ответ.   -  person Martin York    schedule 10.08.2011
comment
Я почти уверен, что new / delete не реализованы, и по уважительной причине это встроенная система. Внимательно прочтите документацию.   -  person Vinicius Kamakura    schedule 10.08.2011
comment
@hexa: хороший улов: nongnu.org/avr-libc/ руководство пользователя / FAQ.html # faq_cplusplus. Вы, наверное, можете опубликовать это как ответ   -  person Alexandre C.    schedule 10.08.2011
comment
@Bracket Я вижу, вы планируете обернуть malloc / free в new / delete. Прочтите, пожалуйста, о фрагментации памяти, это КРИТИЧНО во встроенной среде, или вы думаете, что люди из AVR просто забыли реализовать новое и удалить? У них есть очень веская причина. Начните здесь: stackoverflow.com/questions/3770457/ < / а>   -  person Vinicius Kamakura    schedule 10.08.2011
comment
Я не думал о фрагментации. Я всегда размещаю в куче не более двух вещей. Оба они сохраняются в течение последовательной транзакции перед удалением. У меня 4 КБ ОЗУ, и самые большие объекты, которые я бы выделил, составляют 18 байт, поэтому я не думаю, что это вызовет какие-либо проблемы.   -  person Bracket    schedule 10.08.2011
comment
Забавно, коммерческое ПО в некоторых условиях ведет себя так: libmemcached. clients/clients_memcapable-memcapable.o: In function std :: __ 1 :: allocator ‹char *› :: deallocate (char **, unsigned long) ': / usr / include / c ++ / v1 / memory: 1632: неопределенная ссылка на operator delete(void*)'   -  person Dereckson    schedule 29.04.2015


Ответы (4)


Если вы по какой-то причине не связываетесь со стандартной библиотекой (что вполне может иметь место во встроенном сценарии), вы должны предоставить свои собственные операторы 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);
}

Вам никогда не придется делать это, если вы компилируете для обычной размещенной платформы, поэтому, если вам действительно нужно это сделать, вам лучше ознакомиться с тонкостями управления памятью на вашей платформе.

person Kerrek SB    schedule 10.08.2011
comment
Похоже, для этого чипа нет стандартной библиотеки поддержки: nongnu .org / avr-libc / user-manual / FAQ.html # faq_cplusplus. Поведение new и delete, которое наблюдает OP, даже задокументировано. - person Alexandre C.; 10.08.2011
comment
Я знаю, что есть реализации malloc и free для AVR на C. Если я просто заверну их один раз, будут ли они работать для всех объектов? Куда бы я поместил этот код? - person Bracket; 10.08.2011
comment
Вы помещаете код в любое место в глобальном пространстве имен и связываете его. Если вы не хотите malloc, вы также можете выделить память из некоторой области пула и поддерживать список свободных мест или что-то в этом роде. - person Kerrek SB; 10.08.2011
comment
Хорошо, похоже, это работает (или, по крайней мере, компилируется без ошибок: P). Спасибо! - person Bracket; 10.08.2011
comment
Круто, но будьте осторожны, вам действительно нужно знать, что вы делаете и откуда берете свою память. Я думаю, malloc - очень опасный зверь во встроенном мире, но я не эксперт в этом деле. - person Kerrek SB; 10.08.2011
comment
Это зверь, с которым я боролся раньше, но никогда в C ++. Я внимательно слежу за всем, что выделяется, чтобы убедиться, что это будет удалено позже. - person Bracket; 10.08.2011

Извините за публикацию в старой ветке, но она все еще довольно высока в результатах поиска Google, и если у вас есть эта проблема, вам действительно стоит проверить this link, потому что там написано, что вам просто нужно связать -lstdc ++, и это решило проблему для меня.

Следующая строка была добавлена ​​сообществом без выделения ее как таковой, а вместо простого добавления комментария к моему ответу по причинам, которые ускользают от меня: «Или используйте компилятор C ++, который неявно добавит параметр -lstdc ++, например, g ++».

person Alex    schedule 26.03.2015
comment
К вашему сведению. Связывание в stdc ++ не обязательно решает эту проблему. Я использую -lstdc ++ и тоже пробовал g ++, но все еще вижу эту проблему. - person matt snider; 07.07.2016
comment
Я бился головой о стену уже несколько недель, пытаясь понять, почему мой код CUDA не работает должным образом. Я перепробовал все, что мог найти. Ваш комментарий все исправил, спас положение, решил мою жизнь, и я так вас люблю. Спасибо, спасибо, спасибо, спасибо !!!!! - person boof; 22.02.2017
comment
убедитесь, что -lstdc ++ идет после FWIW - person rogerdpack; 24.02.2018
comment
Решил мою проблему волшебным образом. Спасибо! Для справки более поздних читателей: я пытаюсь связать библиотеку C ++ под названием libzmq из моего встроенного кода Linux C. Если я использую компилятор C ++, все в порядке, но если по какой-то причине мне придется использовать компилятор C. Затем я вижу все эти неопределенные ошибки. Добавление -lstdc++ решает проблему. - person Penghe Geng; 10.10.2018

Я просто процитирую документацию, так как они лучше выразились.

Написание C ++

Вы можете писать программы для платформы AVR на C ++, если вы включили c ++ во включенные языки во время настройки avr-gcc. Практически все, что описано в разделе «Написание программ AVR на C», применимо, так что сначала прочтите это.

Основные недостатки использования 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 ++, с которыми вы привыкли работать, недоступны, возможно, стоит запрограммировать AVR на C ++. Конструкторы и деструкторы функциональны, и только организационные преимущества использования классов и объектно-ориентированного программирования могут сделать C ++ отличным выбором.

person Vinicius Kamakura    schedule 10.08.2011
comment
Я добавлю, что операторы new и delete не реализованы, попытка их использования приведет к тому, что компоновщик будет жаловаться на неопределенные внешние ссылки. (Возможно, это можно исправить.) - person user3125280; 18.01.2014

Если вы просто хотите создать интерфейс, вам не нужно 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

person MikeTwo    schedule 17.11.2012