Skip to content

Commit 5b767a3

Browse files
new w/ OOM now aborts by defaults, or throw an exception (#7536)
* replace `new` by `new (std::nothrow)`, remove `arduino_new` * deleted: arduino_new/arduino_new.ino * fixes * remove (std::nothrow) where nullptr case is not handled remove legacy new management * new w/ OOM raises an exception, shows the caller address for decoders * overwrite weak `new (std::nothrow)` calls * fix displaying caller address * board generator: remove comments, remove now useless define Co-authored-by: Earle F. Philhower, III <earlephilhower@yahoo.com> Co-authored-by: Develo <deveyes@gmail.com>
2 parents be812d2 + ef92ab2 commit 5b767a3

File tree

16 files changed

+134
-423
lines changed

16 files changed

+134
-423
lines changed

boards.txt

Lines changed: 68 additions & 170 deletions
Large diffs are not rendered by default.

cores/esp8266/Esp.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -740,17 +740,17 @@ String EspClass::getSketchMD5()
740740
}
741741
uint32_t lengthLeft = getSketchSize();
742742
const size_t bufSize = 512;
743-
std::unique_ptr<uint8_t[]> buf(new uint8_t[bufSize]);
743+
std::unique_ptr<uint8_t[]> buf(new (std::nothrow) uint8_t[bufSize]);
744744
uint32_t offset = 0;
745745
if(!buf.get()) {
746-
return String();
746+
return emptyString;
747747
}
748748
MD5Builder md5;
749749
md5.begin();
750750
while( lengthLeft > 0) {
751751
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
752752
if (!flashRead(offset, reinterpret_cast<uint32_t*>(buf.get()), (readBytes + 3) & ~3)) {
753-
return String();
753+
return emptyString;
754754
}
755755
md5.add(buf.get(), readBytes);
756756
lengthLeft -= readBytes;

cores/esp8266/Print.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ size_t Print::printf(const char *format, ...) {
6363
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
6464
va_end(arg);
6565
if (len > sizeof(temp) - 1) {
66-
buffer = new char[len + 1];
66+
buffer = new (std::nothrow) char[len + 1];
6767
if (!buffer) {
6868
return 0;
6969
}
@@ -86,7 +86,7 @@ size_t Print::printf_P(PGM_P format, ...) {
8686
size_t len = vsnprintf_P(temp, sizeof(temp), format, arg);
8787
va_end(arg);
8888
if (len > sizeof(temp) - 1) {
89-
buffer = new char[len + 1];
89+
buffer = new (std::nothrow) char[len + 1];
9090
if (!buffer) {
9191
return 0;
9292
}

cores/esp8266/abi.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,33 @@ extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
3232
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
3333

3434

35-
#if !defined(__cpp_exceptions) && !defined(NEW_OOM_ABORT)
36-
void *operator new(size_t size)
35+
#if !defined(__cpp_exceptions)
36+
37+
// overwrite weak operators new/new[] definitions
38+
39+
void* operator new(size_t size)
40+
{
41+
void *ret = malloc(size);
42+
if (0 != size && 0 == ret) {
43+
umm_last_fail_alloc_addr = __builtin_return_address(0);
44+
umm_last_fail_alloc_size = size;
45+
__unhandled_exception(PSTR("OOM"));
46+
}
47+
return ret;
48+
}
49+
50+
void* operator new[](size_t size)
3751
{
3852
void *ret = malloc(size);
3953
if (0 != size && 0 == ret) {
4054
umm_last_fail_alloc_addr = __builtin_return_address(0);
4155
umm_last_fail_alloc_size = size;
56+
__unhandled_exception(PSTR("OOM"));
4257
}
43-
return ret;
58+
return ret;
4459
}
4560

46-
void *operator new[](size_t size)
61+
void* operator new (size_t size, const std::nothrow_t&)
4762
{
4863
void *ret = malloc(size);
4964
if (0 != size && 0 == ret) {
@@ -52,7 +67,18 @@ void *operator new[](size_t size)
5267
}
5368
return ret;
5469
}
55-
#endif // arduino's std::new legacy
70+
71+
void* operator new[] (size_t size, const std::nothrow_t&)
72+
{
73+
void *ret = malloc(size);
74+
if (0 != size && 0 == ret) {
75+
umm_last_fail_alloc_addr = __builtin_return_address(0);
76+
umm_last_fail_alloc_size = size;
77+
}
78+
return ret;
79+
}
80+
81+
#endif // !defined(__cpp_exceptions)
5682

5783
void __cxa_pure_virtual(void)
5884
{

cores/esp8266/cbuf.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919
*/
2020

21+
#include <new> // std::nothrow
2122
#include "cbuf.h"
2223
#include "c_types.h"
2324

@@ -43,7 +44,7 @@ size_t cbuf::resize(size_t newSize) {
4344
return _size;
4445
}
4546

46-
char *newbuf = new char[newSize];
47+
char *newbuf = new (std::nothrow) char[newSize];
4748
char *oldbuf = _buf;
4849

4950
if(!newbuf) {

cores/esp8266/core_esp8266_features.h

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,6 @@
3636
#include <stddef.h> // size_t
3737
#include <stdint.h>
3838

39-
#ifdef __cplusplus
40-
41-
namespace arduino
42-
{
43-
extern "C++"
44-
template <typename T, typename ...TConstructorArgs>
45-
T* new0 (size_t n, TConstructorArgs... TconstructorArgs)
46-
{
47-
// n==0: single allocation, otherwise it is an array
48-
size_t offset = n? sizeof(size_t): 0;
49-
size_t arraysize = n? n: 1;
50-
T* ptr = (T*)malloc(offset + (arraysize * sizeof(T)));
51-
if (ptr)
52-
{
53-
if (n)
54-
*(size_t*)(ptr) = n;
55-
for (size_t i = 0; i < arraysize; i++)
56-
new (ptr + offset + i * sizeof(T)) T(TconstructorArgs...);
57-
return ptr + offset;
58-
}
59-
return nullptr;
60-
}
61-
}
62-
63-
#define arduino_new(Type, ...) arduino::new0<Type>(0, ##__VA_ARGS__)
64-
#define arduino_newarray(Type, n, ...) arduino::new0<Type>(n, ##__VA_ARGS__)
65-
66-
#endif // __cplusplus
67-
6839
#ifndef __STRINGIFY
6940
#define __STRINGIFY(a) #a
7041
#endif

cores/esp8266/core_esp8266_postmortem.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ void __wrap_system_restart_local() {
220220

221221
cut_here();
222222

223+
if (s_unhandled_exception && umm_last_fail_alloc_addr) {
224+
// now outside from the "cut-here" zone, print correctly the `new` caller address,
225+
// idf-monitor.py will be able to decode this one and show exact location in sources
226+
ets_printf_P(PSTR("\nlast failed alloc caller: 0x%08x\n"), (uint32_t)umm_last_fail_alloc_addr);
227+
}
228+
223229
custom_crash_callback( &rst_info, sp_dump + offset, stack_end );
224230

225231
ets_delay_us(10000);

cores/esp8266/debug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ void hexdump(const void *mem, uint32_t len, uint8_t cols);
2222
extern "C" {
2323
#endif
2424

25+
void __unhandled_exception(const char *str) __attribute__((noreturn));
2526
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
2627
#define panic() __panic_func(PSTR(__FILE__), __LINE__, __func__)
2728

doc/reference.rst

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -323,36 +323,3 @@ C++
323323
This assures correct behavior, including handling of all subobjects, which guarantees stability.
324324

325325
History: `#6269 <https://github.com/esp8266/Arduino/issues/6269>`__ `#6309 <https://github.com/esp8266/Arduino/pull/6309>`__ `#6312 <https://github.com/esp8266/Arduino/pull/6312>`__
326-
327-
- New optional allocator ``arduino_new``
328-
329-
A new optional global allocator is introduced with a different semantic:
330-
331-
- never throws exceptions on oom
332-
333-
- never calls constructors on oom
334-
335-
- returns nullptr on oom
336-
337-
It is similar to arduino ``new`` semantic without side effects
338-
(except when parent constructors, or member constructors use ``new``).
339-
340-
Syntax is slightly different, the following shows the different usages:
341-
342-
.. code:: cpp
343-
344-
// with new:
345-
346-
SomeClass* sc = new SomeClass(arg1, arg2, ...);
347-
delete sc;
348-
349-
SomeClass* scs = new SomeClass[42];
350-
delete [] scs;
351-
352-
// with arduino_new:
353-
354-
SomeClass* sc = arduino_new(SomeClass, arg1, arg2, ...);
355-
delete sc;
356-
357-
SomeClass* scs = arduino_newarray(SomeClass, 42);
358-
delete [] scs;

libraries/DNSServer/src/DNSServer.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ void DNSServer::processNextRequest()
178178
return;
179179

180180
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[currentPacketSize]);
181-
182-
if (buffer == NULL)
181+
if (buffer == nullptr)
183182
return;
184183

185184
_udp.read(buffer.get(), currentPacketSize);

0 commit comments

Comments
 (0)