Assertions and Argument Checking
LVGL provides two sets of macros for validating conditions at runtime: assertions and argument checking. This page explains when and how to use each within LVGL's codebase.
LVGL provides two sets of macros for validating conditions at runtime: assertions and argument checking. This page explains when and how to use each within LVGL's codebase. If you are using LVGL rather than contributing to it, see Argument Checking for what these checks mean for your application and how to configure them.
Overview
| Feature | LV_ASSERT | LV_CHECK_ARG |
|---|---|---|
| Purpose | Catch programming errors | Validate runtime input |
| On failure | Halts (LV_ASSERT_HANDLER) | Configurable action |
| Log level | Error | Warning |
| Recovery possible | No | Yes / Maybe |
| Typical use | Internal invariants | API input validation |
Use assertions for conditions that indicate bugs in the code, situations that should never happen if the code is correct. If an internal function expects a parameter to satisfy a certain condition, add an assertion: it acts as executable documentation for future contributors and catches misuse early.
Use argument checking for validating inputs at public API boundaries.
LV_CHECK_ARG (and LV_CHECK_OBJ*) are mandatory at the start
of every public API function, they allow callers to recover gracefully and
produce actionable log output when something goes wrong.
Assertions
Assertions check for programming errors and halt the program when they fail. They are typically enabled only in debug builds and may be disabled in release builds.
Configuration
Enable assertions in lv_conf.h:
LV_USE_ASSERT_NULL- Check for NULL pointersLV_USE_ASSERT_MALLOC- Check for failed memory allocationsLV_USE_ASSERT_MEM_INTEGRITY- Check memory integrity
Configure the assert handler with LV_ASSERT_HANDLER. The default
behavior is while(1); which halts the program.
Usage
LV_ASSERT
Basic assertion with the condition stringified in the log message:
LV_ASSERT(pi > 0);LV_ASSERT_MSG
Assertion with a plain string message:
LV_ASSERT_MSG(pi > 0, "pi should be positive");LV_ASSERT_FORMAT_MSG
Assertion with a printf-style format message:
LV_ASSERT_FORMAT_MSG(pi > 0, ": was %f", pi);Specialized Assertions
LV_ASSERT_NULL
Check that a pointer is not NULL:
LV_ASSERT_NULL(obj);LV_ASSERT_MALLOC
Check that a memory allocation succeeded:
void * buf = lv_malloc(size);
LV_ASSERT_MALLOC(buf);LV_ASSERT_MEM_INTEGRITY
Check that LVGL's memory pool is not corrupted:
LV_ASSERT_MEM_INTEGRITY();Argument Checking
The LV_CHECK_ARG macro provides a flexible approach for validating
function arguments at runtime: it logs a warning and allows you to specify a
recovery action (such as returning from a function or continuing with a fallback).
This macro is useful for:
- Input validation at the start of functions
- Checking preconditions without halting the program
- Defensive programming with graceful error handling
- Logging invariant violations that may not be critical but should be noted
Configuration
-
LV_USE_CHECK_ARG— Set to1to enable,0to disable. Enabled by default. When disabled, allLV_CHECK_ARGandLV_CHECK_OBJcalls compile to nothing.Disabling argument checks is dangerous
With
LV_USE_CHECK_ARG = 0, passing invalid arguments to any public API function is undefined behavior — there is no NULL guard, no type check, and no early return. Only disable this if you can guarantee that every call site in your application passes valid arguments. When in doubt, leave it enabled. -
LV_CHECK_ARG_ASSERT_ON_FAIL— Set to1to also callLV_ASSERT_HANDLERon failure (before the action is executed). Useful during debugging to restore hard-abort behavior. -
LV_CHECK_ARG_LOG_MODE— Controls how much is logged when a check fails. RequiresLV_USE_LOG = 1; if logging is disabled no output is produced regardless of this setting.LV_CHECK_ARG_LOG_MODE_NONE (0)— No log output.LV_CHECK_ARG_LOG_MODE_MINIMAL (1)— Logs"Check failed"plus file and line number.LV_CHECK_ARG_LOG_MODE_VERBOSE (2)— Logs"Check failed: <cond>"plus any caller-supplied message.
Usage
LV_CHECK_ARG takes a condition and an action to execute on
failure. LV_CHECK_ARG_MSG also takes a message and
LV_CHECK_ARG_FORMAT_MSG a printf-style format string with its
arguments:
void draw_to_display(lv_obj_t * display, int len)
{
/* Return early if display is NULL */
LV_CHECK_ARG_MSG(display != NULL, return, "display must be provided");
/* Return if len is invalid, logging the actual value */
LV_CHECK_ARG_FORMAT_MSG(len % 2 == 0, return, "need even data points, but got %d", (int)len);
}
int get_width(lv_obj_t * obj)
{
/* Return -1 if obj is NULL */
LV_CHECK_ARG(obj != NULL, return -1);
/* ... */
}The condition is stringified and included in the log message, so you can see exactly what check failed. Only supply a message, or a format string and arguments, if you want to include additional context beyond the condition itself.
Object Checking
LV_CHECK_OBJ is the standard replacement for LV_ASSERT_OBJ and
the only object-checking macro you should use directly. It performs all checks
enabled by the configuration (see below) and requires
LV_USE_CHECK_ARG = 1:
LV_CHECK_OBJ(obj, &lv_label_class, return);LV_CHECK_OBJ_CLASS and LV_CHECK_OBJ_VALID are
lower-level building blocks exposed for completeness. Do not use them directly.
Configuration
The checks performed by LV_CHECK_OBJ macros are layered and independently configurable:
| Layer | Config option | What it checks |
|---|---|---|
| Base | LV_USE_CHECK_ARG = 1 | Master switch. When 0, all three macros expand to nothing. |
| NULL | always on | obj != NULL (always checked when the system is enabled). |
| Class type | LV_USE_CHECK_OBJ_CLASSTYPE = 1 | lv_obj_has_class(obj, cls) — verifies the object is the expected widget type. |
| Validity | LV_USE_CHECK_OBJ_VALIDITY = 1 | lv_obj_is_in_widget_tree(obj) — verifies the object is still part of the live widget tree. |
LV_USE_CHECK_ARG defaults to 1; both LV_USE_CHECK_OBJ_* options default
to 0. Enable them selectively:
/* lv_conf.h */
#define LV_USE_CHECK_ARG 1 /* master switch — enables LV_CHECK_ARG and LV_CHECK_OBJ* */
#define LV_USE_CHECK_OBJ_CLASSTYPE 1 /* also verify the object's class type */
#define LV_USE_CHECK_OBJ_VALIDITY 1 /* also verify the object is alive in the widget tree */Enable only during development
lv_obj_is_in_widget_tree() walks the widget tree and lv_obj_has_class() traverses
the class hierarchy on every call site. These checks add non-trivial overhead,
especially in rendering-critical code paths. Keep LV_USE_CHECK_OBJ_CLASSTYPE
and LV_USE_CHECK_OBJ_VALIDITY at 0 in production builds.
Macros Reference
Assertions
| Macro | Description |
|---|---|
LV_ASSERT | Assert condition; on failure log and halt |
LV_ASSERT_MSG | Assert with plain string message |
LV_ASSERT_FORMAT_MSG | Assert with printf-style format message |
LV_ASSERT_NULL | Assert pointer is not NULL (if enabled) |
LV_ASSERT_MALLOC | Assert allocation succeeded (if enabled) |
LV_ASSERT_MEM_INTEGRITY | Assert memory pool integrity (if enabled) |
Argument Checking
| Macro | Description |
|---|---|
LV_CHECK_ARG | Check condition; on failure log and execute action |
Object Checking
| Macro | Description |
|---|---|
LV_CHECK_OBJ | NULL + optional class type + optional validity check (preferred) |
LV_CHECK_OBJ_CLASS | NULL + optional class type check |
LV_CHECK_OBJ_VALID | NULL + optional class type + optional validity check (alias for LV_CHECK_OBJ) |
Last updated on