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
+36-64Lines changed: 36 additions & 64 deletions
Original file line number
Diff line number
Diff line change
@@ -219,28 +219,13 @@ using FPSTR would become...
219
219
C++
220
220
----
221
221
222
-
- About C++ ``operator new`` and return value and its replacement ``new0<>()``
223
-
224
-
In short, it is preferred for stability to use new `new0` instead of `new`:
225
-
226
-
.. code:: cpp
227
-
228
-
SomeClass* sc = new0<SomeClass>(arg1, arg2, ...);
229
-
// abort() is never called, an exception is not thrown even if they are enabled
230
-
if (sc == nullptr)
231
-
{
232
-
// failed allocation, handle here
233
-
}
234
-
else
235
-
{
236
-
// use sc
237
-
}
222
+
- About C++ exceptions, ``operator new``, and Exceptions menu option
238
223
239
224
The C++ standard says the following about the ``new`` operator behavior when encountering heap shortage (memory full):
240
225
241
-
- has to throw a ``std::bad_alloc`` C++ exception
226
+
- has to throw a ``std::bad_alloc`` C++ exception when they are enabled
242
227
243
-
- throw an unhandled exception, which means calling ``abort()``
228
+
- will ``abort()`` otherwise
244
229
245
230
There are several reasons for the first point above, among which are:
246
231
@@ -250,59 +235,46 @@ C++
250
235
251
236
- guarantee that any subobjects partially constructed get destroyed, and in the correct order, if oom is encountered midway through construction
252
237
253
-
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.
238
+
When C++ exceptions are disabled, or when using ``new(nothrow)``, the above guarantees can't be upheld, so the second point (``abort()``) above is the only ``std::c++`` viable solution.
254
239
255
-
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.
240
+
Historically in Arduino environments, ``new`` is overloaded to simply return the equivalent ``malloc()`` which in turn can return ``nullptr``.
256
241
257
-
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.
242
+
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``).
243
+
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.
244
+
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.
245
+
Luckily on esp8266, trying to update RAM near address 0 will immediately raise an hardware exception, unlike on other uC like avr on which that memory can be accessible.
258
246
259
-
As of core 2.6.0, we are sticking to the C++ standard. There are two clear cases when ``new`` encounters oom:
247
+
As of core 2.6.0, there are 3 options: legacy (default) and two clear cases when ``new`` encounters oom:
248
+
249
+
- ``new`` returns ``nullptr``, with possible bad effects or immediate crash when constructors (called anyway) initialize members (exceptions are disabled in this case)
260
250
261
-
- 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.
251
+
- C++ exceptions are disabled: ``new`` calls ``abort()`` and will "cleanly" crash, because there is no way to honor memory allocation or to recover gracefully.
252
+
253
+
- C++ exceptions are enabled: ``new`` throws a ``std::bad_alloc`` C++ exception, which can be caught and handled gracefully.
254
+
This assures correct behavior, including handling of all subobjects, which guarantees stability.
A new optional global allocator is introduced with a different semantic:
261
+
262
+
- never throws exceptions on oom
263
+
264
+
- never calls constructors on oom
265
+
266
+
- returns nullptr (without side effects - excepted when parent constructors, or member constructors use ``new``)
267
+
268
+
It is similar to arduino ``new`` semantic without side effects.
262
269
263
-
- 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.
264
-
265
-
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.
266
-
267
270
Syntax is slightly different, the following shows the different usages:
268
-
271
+
269
272
C++ standard behavior (as of 2.6.0):
270
-
271
-
.. code:: cpp
272
-
273
-
SomeClass* sc = new SomeClass(arg1, arg2, ...);
274
-
// sc is always valid and not nullptr, no check necessary
275
-
// abort() gets called (crash dump, reboot) if oom,
276
-
// or a C++ std::bad_alloc exception is thrown when available
277
-
278
-
Old behavior (until 2.5.2):
279
-
273
+
280
274
.. code:: cpp
281
-
275
+
276
+
// with new:
282
277
SomeClass* sc = new SomeClass(arg1, arg2, ...);
283
-
// abort() is never called, an exception is not thrown even if they are enabled
284
-
if (sc == nullptr)
285
-
{
286
-
// failed allocation, handle here, possible bad hidden effects
287
-
}
288
-
else
289
-
{
290
-
// use sc
291
-
}
292
-
293
-
Alternate behavior (as of 2.6.0):
294
-
295
-
.. code:: cpp
296
-
278
+
279
+
// with new0
297
280
SomeClass* sc = new0<SomeClass>(arg1, arg2, ...);
298
-
// abort() is never called, an exception is not thrown even if they are enabled
0 commit comments