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.

Edit on GitHub

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

FeatureLV_ASSERTLV_CHECK_ARG
PurposeCatch programming errorsValidate runtime input
On failureHalts (LV_ASSERT_HANDLER)Configurable action
Log levelErrorWarning
Recovery possibleNoYes / Maybe
Typical useInternal invariantsAPI 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 pointers
  • LV_USE_ASSERT_MALLOC - Check for failed memory allocations
  • LV_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 to 1 to enable, 0 to disable. Enabled by default. When disabled, all LV_CHECK_ARG and LV_CHECK_OBJ calls 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 to 1 to also call LV_ASSERT_HANDLER on 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. Requires LV_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:

LayerConfig optionWhat it checks
BaseLV_USE_CHECK_ARG = 1Master switch. When 0, all three macros expand to nothing.
NULLalways onobj != NULL (always checked when the system is enabled).
Class typeLV_USE_CHECK_OBJ_CLASSTYPE = 1lv_obj_has_class(obj, cls) — verifies the object is the expected widget type.
ValidityLV_USE_CHECK_OBJ_VALIDITY = 1lv_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

MacroDescription
LV_ASSERTAssert condition; on failure log and halt
LV_ASSERT_MSGAssert with plain string message
LV_ASSERT_FORMAT_MSGAssert with printf-style format message
LV_ASSERT_NULLAssert pointer is not NULL (if enabled)
LV_ASSERT_MALLOCAssert allocation succeeded (if enabled)
LV_ASSERT_MEM_INTEGRITYAssert memory pool integrity (if enabled)

Argument Checking

MacroDescription
LV_CHECK_ARGCheck condition; on failure log and execute action

Object Checking

MacroDescription
LV_CHECK_OBJNULL + optional class type + optional validity check (preferred)
LV_CHECK_OBJ_CLASSNULL + optional class type check
LV_CHECK_OBJ_VALIDNULL + optional class type + optional validity check (alias for LV_CHECK_OBJ)

Last updated on

On this page