Skip to content

Improve and complete implementation of new/delete #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Oct 15, 2020
15 changes: 8 additions & 7 deletions cores/arduino/abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@
extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));

namespace std {
[[gnu::weak, noreturn]] void terminate() {
abort();
}
}

void __cxa_pure_virtual(void) {
// We might want to write some diagnostics to uart in this case
//std::terminate();
abort();
std::terminate();
}

void __cxa_deleted_virtual(void) {
// We might want to write some diagnostics to uart in this case
//std::terminate();
abort();
std::terminate();
}

67 changes: 64 additions & 3 deletions cores/arduino/new
Original file line number Diff line number Diff line change
@@ -1,5 +1,66 @@
/*
this header is for compatibility with standard c++ header names
so that #include<new> works as expected
Copyright (c) 2014 Arduino. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "new.h"

#ifndef NEW_H
#define NEW_H

#include <stdlib.h>

namespace std {
struct nothrow_t {};
extern const nothrow_t nothrow;

// These are not actually implemented, to prevent overhead and
// complexity. They are still declared to allow implementing
// them in user code if needed.
typedef void (*new_handler)();
new_handler set_new_handler(new_handler new_p) noexcept;
new_handler get_new_handler() noexcept;

// This is normally declared in various headers that we do not have
// available, so just define it here. We could also use ::size_t
// below, but then anyone including <new> can no longer assume
// std::size_t is available.
using size_t = ::size_t;
} // namespace std

[[gnu::weak]] void * operator new(std::size_t size);
[[gnu::weak]] void * operator new[](std::size_t size);

[[gnu::weak]] void * operator new(std::size_t size, const std::nothrow_t tag) noexcept;
[[gnu::weak]] void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept;

void * operator new(std::size_t size, void *place) noexcept;
void * operator new[](std::size_t size, void *place) noexcept;

[[gnu::weak]] void operator delete(void * ptr) noexcept;
[[gnu::weak]] void operator delete[](void * ptr) noexcept;

#if __cplusplus >= 201402L
[[gnu::weak]] void operator delete(void* ptr, std::size_t size) noexcept;
[[gnu::weak]] void operator delete[](void * ptr, std::size_t size) noexcept;
#endif // __cplusplus >= 201402L

[[gnu::weak]] void operator delete(void* ptr, const std::nothrow_t& tag) noexcept;
[[gnu::weak]] void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept;

void operator delete(void* ptr, void* place) noexcept;
void operator delete[](void* ptr, void* place) noexcept;

#endif

96 changes: 86 additions & 10 deletions cores/arduino/new.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,102 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
#include "new.h"

void *operator new(size_t size) {
return malloc(size);
// The C++ spec dicates that allocation failure should cause the
// (non-nothrow version of the) operator new to throw an exception.
// Since we expect to have exceptions disabled, it would be more
// appropriate (and probably standards-compliant) to terminate instead.
// Historically failure causes null to be returned, but this define
// allows switching to more robust terminating behaviour (that might
// become the default at some point in the future). Note that any code
// that wants null to be returned can (and should) use the nothrow
// versions of the new statement anyway and is unaffected by this.
// #define NEW_TERMINATES_ON_FAILURE

namespace std {
// Defined in abi.cpp
void terminate();

const nothrow_t nothrow;
}

void *operator new[](size_t size) {
static void * new_helper(std::size_t size) {
// Even zero-sized allocations should return a unique pointer, but
// malloc does not guarantee this
if (size == 0)
size = 1;
return malloc(size);
}

void * operator new(size_t size, void * ptr) noexcept {
(void)size;
return ptr;
void * operator new(std::size_t size) {
void *res = new_helper(size);
#if defined(NEW_TERMINATES_ON_FAILURE)
if (!res)
std::terminate();
#endif
return res;
}
void * operator new[](std::size_t size) {
return operator new(size);
}

void operator delete(void * ptr) {
free(ptr);
void * operator new(std::size_t size, const std::nothrow_t tag) noexcept {
#if defined(NEW_TERMINATES_ON_FAILURE)
// Cannot call throwing operator new as standard suggests, so call
// new_helper directly then
return new_helper(size);
#else
return operator new(size);
#endif
}
void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept {
#if defined(NEW_TERMINATES_ON_FAILURE)
// Cannot call throwing operator new[] as standard suggests, so call
// malloc directly then
return new_helper(size);
#else
return operator new[](size);
#endif
}

void * operator new(std::size_t size, void *place) noexcept {
// Nothing to do
(void)size; // unused
return place;
}
void * operator new[](std::size_t size, void *place) noexcept {
return operator new(size, place);
}

void operator delete[](void * ptr) {
void operator delete(void * ptr) noexcept {
free(ptr);
}
void operator delete[](void * ptr) noexcept {
operator delete(ptr);
}

#if __cplusplus >= 201402L
void operator delete(void* ptr, std::size_t size) noexcept {
operator delete(ptr);
}
void operator delete[](void * ptr, std::size_t size) noexcept {
operator delete[](ptr);
}
#endif // __cplusplus >= 201402L

void operator delete(void* ptr, const std::nothrow_t& tag) noexcept {
operator delete(ptr);
}
void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept {
operator delete[](ptr);
}

void operator delete(void* ptr, void* place) noexcept {
(void)ptr; (void)place; // unused
// Nothing to do
}
void operator delete[](void* ptr, void* place) noexcept {
(void)ptr; (void)place; // unused
// Nothing to do
}
34 changes: 3 additions & 31 deletions cores/arduino/new.h
Original file line number Diff line number Diff line change
@@ -1,31 +1,3 @@
/*
Copyright (c) 2014 Arduino. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef NEW_H
#define NEW_H

#include <stdlib.h>

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

#endif

// This file originally used a non-standard name for this Arduino core
// only, so still expose the old new.h name for compatibility.
#include "new"