mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 05:04:33 +02:00
docs: Add section about assertions to the style guide
This commit is contained in:
@@ -10,13 +10,13 @@ Overview
|
|||||||
Identifying and handling run-time errors is important for developing robust applications. There can be multiple kinds of run-time errors:
|
Identifying and handling run-time errors is important for developing robust applications. There can be multiple kinds of run-time errors:
|
||||||
|
|
||||||
- Recoverable errors:
|
- Recoverable errors:
|
||||||
|
|
||||||
- Errors indicated by functions through return values (error codes)
|
- Errors indicated by functions through return values (error codes)
|
||||||
- C++ exceptions, thrown using ``throw`` keyword
|
- C++ exceptions, thrown using ``throw`` keyword
|
||||||
|
|
||||||
- Unrecoverable (fatal) errors:
|
- Unrecoverable (fatal) errors:
|
||||||
|
|
||||||
- Failed assertions (using ``assert`` macro and equivalent methods) and ``abort()`` calls.
|
- Failed assertions (using ``assert`` macro and equivalent methods, see :ref:`assertions`) and ``abort()`` calls.
|
||||||
- CPU exceptions: access to protected regions of memory, illegal instruction, etc.
|
- CPU exceptions: access to protected regions of memory, illegal instruction, etc.
|
||||||
- System level checks: watchdog timeout, cache access error, stack overflow, stack smashing, heap corruption, etc.
|
- System level checks: watchdog timeout, cache access error, stack overflow, stack smashing, heap corruption, etc.
|
||||||
|
|
||||||
@@ -43,6 +43,8 @@ Additionally, :cpp:func:`esp_err_to_name_r` function will attempt to interpret t
|
|||||||
|
|
||||||
This feature is enabled by default, but can be disabled to reduce application binary size. See :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP`. When this feature is disabled, :cpp:func:`esp_err_to_name` and :cpp:func:`esp_err_to_name_r` are still defined and can be called. In this case, :cpp:func:`esp_err_to_name` will return ``UNKNOWN ERROR``, and :cpp:func:`esp_err_to_name_r` will return ``Unknown error 0xXXXX(YYYYY)``, where ``0xXXXX`` and ``YYYYY`` are the hexadecimal and decimal representations of the error code, respectively.
|
This feature is enabled by default, but can be disabled to reduce application binary size. See :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP`. When this feature is disabled, :cpp:func:`esp_err_to_name` and :cpp:func:`esp_err_to_name_r` are still defined and can be called. In this case, :cpp:func:`esp_err_to_name` will return ``UNKNOWN ERROR``, and :cpp:func:`esp_err_to_name_r` will return ``Unknown error 0xXXXX(YYYYY)``, where ``0xXXXX`` and ``YYYYY`` are the hexadecimal and decimal representations of the error code, respectively.
|
||||||
|
|
||||||
|
.. _esp-error-check-macro:
|
||||||
|
|
||||||
``ESP_ERROR_CHECK`` macro
|
``ESP_ERROR_CHECK`` macro
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@@ -217,6 +217,46 @@ Enums should be defined through the `typedef` and be namespaced::
|
|||||||
MODULE_FOO_THREE
|
MODULE_FOO_THREE
|
||||||
} module_foo_t;
|
} module_foo_t;
|
||||||
|
|
||||||
|
|
||||||
|
.. _assertions:
|
||||||
|
|
||||||
|
Assertions
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
The standard C ``assert()`` function, defined in ``assert.h`` should be used to check conditions that should be true in source code. In the default configuration, an assert condition that returns ``false`` or 0 will call ``abort()`` and trigger a :doc:`Fatal Error</api-guides/fatal-errors>`.
|
||||||
|
|
||||||
|
``assert()`` should only be used to detect unrecoverable errors due to a serious internal logic bug or corruption, where it's not possible for the program to continue. For recoverable errors, including errors that are possible due to invalid external input, an :doc:`error value should be returned </api-guides/error-handling>`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When asserting a value of type ``esp_err_t``is equal to ``ESP_OK``, use the :ref:`esp-error-check-macro` instead of an ``assert()``.
|
||||||
|
|
||||||
|
It's possible to configure ESP-IDF projects with assertions disabled (see :ref:`CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL`). Therefore, functions called in an ``assert()`` statement should not have side-effects.
|
||||||
|
|
||||||
|
It's also necessary to use particular techniques to avoid "variable set but not used" warnings when assertions are disabled, due to code patterns such as::
|
||||||
|
|
||||||
|
int res = do_something();
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
|
Once the ``assert`` is optimized out, the ``res`` value is unused and the compiler will warn about this. However the function ``do_something()`` must still be called, even if assertions are disabled.
|
||||||
|
|
||||||
|
When the variable is declared and initialized in a single statement, a good strategy is to cast it to ``void`` on a new line. The compiler will not produce a warning, and the variable can still be optimized out of the final binary::
|
||||||
|
|
||||||
|
int res = do_something();
|
||||||
|
assert(res == 0);
|
||||||
|
(void)res;
|
||||||
|
|
||||||
|
If the variable is declared separately, for example if it is used for multiple assertions, then it can be declared with the GCC attribute ``__attribute__((unused))``. The compiler will not produce any unused variable warnings, but the variable can still be optimized out::
|
||||||
|
|
||||||
|
int res __attribute__((unused));
|
||||||
|
|
||||||
|
res = do_something();
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
|
res = do_something_else();
|
||||||
|
assert(res != 0);
|
||||||
|
|
||||||
|
|
||||||
C++ Code Formatting
|
C++ Code Formatting
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user