Skip to content

Commit 0aa4c1b

Browse files
committed
doc
1 parent 7daaec9 commit 0aa4c1b

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

doc/reference.rst

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,22 +222,29 @@ C++
222222
- About C++ `new` operator and return value
223223

224224
The C++ standard says the following about the `new` operator behavior when encountering heap shortage (memory full):
225+
225226
- has to throw a std::bad_alloc C++ exception
227+
226228
- throw an unhandled exception, which means calling abort()
227229

228230
There are several reasons for the first point above, among which are:
231+
229232
- guarantee that the return of new is never a nullptr
233+
230234
- guarantee full construction of the top level object plus all member subobjects
235+
231236
- guarantee that any subobjects partially constructed get destroyed, and in the correct order, if oom is encountered midway through construction
232237

233238
When C++ exceptions are disabled, or when using new(nothrow), the above guarantees can't be upheld, so the second point above is the only viable solution.
234239

235240
Historically in Arduino environments, `new` is overloaded to simply return the equivalent `malloc()` which in turn can return `nullptr`. In other cores, and up to our core version 2.5.2, that is considered as acceptable.
236241

237242
However, this behavior is not C++ standard, and there is good reason for that: there are hidden and very bad side effects. The class and member constructors are always called, even when memory is full (`this`=`nullptr`). In addition, the memory allocation for the top object could succeed, but allocation required for some member object could fail, leaving construction in an undefined state. So the historical behavior of Ardudino's `new`, when faced with insufficient memory, will lead to bad crashes sooner or later, sometimes unexplainable, generally due to memory corruption even when the returned value is checked and managed.
238-
243+
239244
As of core 2.6.0, we are sticking to the C++ standard. There are two clear cases when `new` encounters oom:
245+
240246
- C++ exceptions are disabled (default build): `new` causes an exception, which in turn calls `abort()` and will "cleanly" crash, because there is no way to honor memory allocation or to recover gracefully.
247+
241248
- C++ exceptions are enabled (menu option): `new` throws a std::bad_alloc C++ exception, which can be caught and handled gracefully. This assures correct behavior, including handling of all subobjects, which guarantees stability.
242249

243250
To allow previous behavior, a new optional global allocator is introduced with a different semantic. It is similar to `new` but will return `nullptr` without side effects (if `std::new` is not used in constructors), as expected in arduino world. Syntax is slightly different:
@@ -257,7 +264,7 @@ C++
257264

258265
.. code:: cpp
259266
260-
SomeClass* sc = new0<SomeClass>(arg1, arg2, ...);
267+
SomeClass* sc = new SomeClass(arg1, arg2, ...);
261268
// abort() is never called, an exception is not thrown even if they are enabled
262269
if (sc == nullptr)
263270
{

0 commit comments

Comments
 (0)