diff --git a/esphome/components/esp32/operator_new.cpp b/esphome/components/esp32/operator_new.cpp index eca94421601..dbe5e576630 100644 --- a/esphome/components/esp32/operator_new.cpp +++ b/esphome/components/esp32/operator_new.cpp @@ -10,6 +10,7 @@ #include #ifndef CONFIG_COMPILER_CXX_EXCEPTIONS +#include #include #include #include "esp_system.h" @@ -41,5 +42,32 @@ void *operator new(std::size_t size) { void *operator new[](std::size_t size) { return ::operator new(size); } void *operator new[](std::size_t size, const std::nothrow_t &tag) noexcept { return ::operator new(size, tag); } +// Aligned forms; libstdc++'s aligned delete frees with free(), which matches memalign() +void *operator new(std::size_t size, std::align_val_t align, const std::nothrow_t & /*tag*/) noexcept { + if (size == 0) + size = 1; + for (;;) { + void *ptr = memalign(static_cast(align), size); + if (ptr != nullptr) + return ptr; + std::new_handler handler = std::get_new_handler(); + if (handler == nullptr) + return nullptr; + handler(); + } +} + +void *operator new(std::size_t size, std::align_val_t align) { + void *ptr = ::operator new(size, align, std::nothrow); // NOLINT: this is the nothrow form being fixed + if (ptr == nullptr) + esp_system_abort("std::bad_alloc"); + return ptr; +} + +void *operator new[](std::size_t size, std::align_val_t align) { return ::operator new(size, align); } +void *operator new[](std::size_t size, std::align_val_t align, const std::nothrow_t &tag) noexcept { + return ::operator new(size, align, tag); +} + #endif // CONFIG_COMPILER_CXX_EXCEPTIONS #endif // USE_ESP_IDF diff --git a/script/ci-custom.py b/script/ci-custom.py index 1b3abc40f2d..af862e54889 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -1257,9 +1257,9 @@ def lint_no_std_bind(fname, match): ) def lint_no_std_nothrow(fname, match): return ( - f"{highlight('new (std::nothrow)')} aborts on ESP-IDF when the allocation fails, exceptions are disabled " - f"there, so it never returns nullptr.\n" - f"Please use {highlight('RAMAllocator')} from esphome/core/helpers.h, which does.\n" + f"Please use {highlight('RAMAllocator')} from esphome/core/helpers.h instead of " + f"{highlight('new (std::nothrow)')}: it returns nullptr on failure on every platform and lets you choose PSRAM " + f"or internal RAM.\n" f" Before: {highlight('auto *buf = new (std::nothrow) uint8_t[n];')}\n" f" After: {highlight('auto buf = RAMAllocator().make_unique_array_for_overwrite(n);')}\n" f"For one object use {highlight('RAMAllocator().make_unique(args...)')}; both return empty on failure.\n"