Неопределенный оператор delete

Код

class Test {};

void setup() {
    Test * t = new Test();
    delete t;
}

Компилирую скетч для Ардуино на cmake + avr. На строчке с delete Получаю ошибку

undefined reference to `operator delete(void*, unsigned int)'

это что такое? Зачем компилятор (а вернее линковщик) требует переопределения оператора delete да еще и с такими параметрами?

Содержимое CMakeList.txt

cmake_minimum_required(VERSION 2.8.4)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake)
set(CMAKE_CXX_STANDARD 17)
set(PROJECT_NAME Controller)

set(${PROJECT_NAME}_BOARD uno)
# set(ARDUINO_CPU)
project(${PROJECT_NAME})

include_directories(${PROJECT_SOURCE_DIR})
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
file(GLOB HDR_FILES ${PROJECT_SOURCE_DIR}/*.h)

set(${PROJECT_NAME}_SRCS ${SRC_FILES})
set(${PROJECT_NAME}_HDRS ${HDR_FILES})

set(${PROJECT_NAME}_PORT COM4)

generate_arduino_firmware(${PROJECT_NAME}
        SRCS ${${PROJECT_NAME}_SRCS}
        HDRS ${${PROJECT_NAME}_HDRS}
        )

print_board_list()
print_programmer_list()

Ответы (2 шт):

Автор решения: Maxim Timakov

Это происходит, так как avr-g++ не поддерживает libstdc++

Из avr-libc FAQ

Can I use C++ on the AVR?

Basically yes, C++ is supported (assuming your compiler has been configured and compiled to support it, of course). Source files ending in .cc, .cpp or .C will automatically cause the compiler frontend to invoke the C++ compiler. Alternatively, the C++ compiler could be explicitly called by the name avr-c++.

However, there's currently no support for libstdc++, the standard support library needed for a complete C++ implementation. This imposes a number of restrictions on the C++ programs that can be compiled. Among them are:

  • Obviously, none of the C++ related standard functions, classes, and template classes are available.
  • The operators new and delete are not implemented, attempting to use them will cause the linker to complain about undefined external references. (This could perhaps be fixed.)
  • Some of the supplied include files are not C++ safe, i. e. they need to be wrapped into extern "C" { . . . } (This could certainly be fixed, too.)
  • Exceptions are not supported. Since exceptions are enabled by default in the C++ frontend, they explicitly need to be turned off using -fno-exceptions in the compiler options. Failing this, the linker will complain about an undefined external reference to __gxx_personality_sj0. Constructors and destructors are supported though, including global ones.

When programming C++ in space- and runtime-sensitive environments like microcontrollers, extra care should be taken to avoid unwanted side effects of the C++ calling conventions like implied copy constructors that could be called upon function invocation etc. These things could easily add up into a considerable amount of time and program memory wasted. Thus, casual inspection of the generated assembler code (using the -S compiler option) seems to be warranted.

Библиотека arduino содержит реализацию new/delete(файлы new.cpp и new.h), но используемый Вами скрипт ArduinoToolchain.cmake не подключает их при сборке библиотеки arduino core

Вы можете попробовать другую реализацию Arduino Toolchain для cmake

Например, https://github.com/a9183756-gh/Arduino-CMake-Toolchain

Пример файл проекта для cmake:

cmake_minimum_required(VERSION 3.10)

project(test_uno CXX)

add_executable(test_uno main.cpp)

target_link_arduino_libraries(test_uno PRIVATE core)

target_enable_arduino_upload(test_uno)

Параметры cmake:

cmake \
   -DCMAKE_TOOLCHAIN_FILE=/path/to/Arduino-toolchain.cmake \
   -DARDUINO_BOARD="avr.uno" \
   /path/to/sources.dir
//main.cpp
#include <Arduino.h>

class Test {};

void setup() {
    Test * t = new Test();
    delete t;
}

void loop() {}
→ Ссылка
Автор решения: Anton Shchyrov

В C++14 появился перегруженный оператор delete

void operator delete  ( void* ptr, std::size_t sz ) noexcept;

который удаляет память указанного размера. В ардуиновской библиотеке определены только такие варианты

void * operator new(size_t size);
void * operator new[](size_t size);
void * operator new(size_t size, void * ptr) noexcept;
void operator delete(void * ptr);
void operator delete[](void * ptr); 

Я понизил в CMakeLists.txt версию с++ до 11

set(CMAKE_CXX_STANDARD 11)

и все стало компилироваться

→ Ссылка