You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/reference.rst
+9-2Lines changed: 9 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -222,22 +222,29 @@ C++
222
222
- About C++ `new` operator and return value
223
223
224
224
The C++ standard says the following about the `new` operator behavior when encountering heap shortage (memory full):
225
+
225
226
- has to throw a std::bad_alloc C++ exception
227
+
226
228
- throw an unhandled exception, which means calling abort()
227
229
228
230
There are several reasons for the first point above, among which are:
231
+
229
232
- guarantee that the return of new is never a nullptr
233
+
230
234
- guarantee full construction of the top level object plus all member subobjects
235
+
231
236
- guarantee that any subobjects partially constructed get destroyed, and in the correct order, if oom is encountered midway through construction
232
237
233
238
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.
234
239
235
240
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.
236
241
237
242
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
+
239
244
As of core 2.6.0, we are sticking to the C++ standard. There are two clear cases when `new` encounters oom:
245
+
240
246
- 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
+
241
248
- 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.
242
249
243
250
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++
257
264
258
265
.. code:: cpp
259
266
260
-
SomeClass* sc = new0<SomeClass>(arg1, arg2, ...);
267
+
SomeClass* sc = new SomeClass(arg1, arg2, ...);
261
268
// abort() is never called, an exception is not thrown even if they are enabled
0 commit comments