zerror.h is a sophisticated, single-header error handling library for C and C++. It bridges the gap between low-level C programming and modern safety patterns found in languages like Rust or Swift by providing Result types, stack traces, and "Logical Stack Traces" through macro-driven decoration.
It is part of the Zen Development Kit.
- Type-Safe Results: Generic
result<T>patterns for both C (via macros) and C++. - Logical Stack Traces: Capture file, line, and function names at the point of origin and throughout the propagation chain.
- Zero-Allocation Printing: Uses thread-local ring buffers for error message formatting to avoid heap fragmentation.
- C++ Support: Native C++11 wrapper with RAII
result<T>andstd::ostreamintegration. - Modern C Ergonomics: Leverages
__attribute__((cleanup))and statement expressions fortry-like syntax on supported compilers. - Debug Integration: Optional hardware breakpoints/traps (
ZERROR_TRAP) when an error is created.
Define result types and use the propagation macros to handle errors without boilerplate.
#define ZERROR_IMPLEMENTATION
#include "zerror.h"
// Define a Result type that can return an int or a zerr.
DEFINE_RESULT(int, ResInt)
ResInt calculate(int val)
{
if (val < 0)
{
// Creates error with file/line/func context.
return ResInt_err(zerr_create(Z_EINVAL, "Value cannot be negative: %d", val));
}
return ResInt_ok(val * 2);
}
zres process()
{
// 'try' automatically unwraps value or returns error to caller.
int x = try(calculate(-5));
printf("Result: %d\n", x);
return zres_ok();
}
int main()
{
// 'run' executes the logic and prints a formatted trace on failure.
return run(process());
}The C++ wrapper lives in the z_error namespace and provides a template-based result<T> that behaves similarly to std::expected.
#include <iostream>
#define ZERROR_IMPLEMENTATION
#include "zerror.h"
z_error::result<int> compute(int n)
{
if (n == 0)
{
return zerr_create(Z_ERR, "Division by zero");
}
return 100 / n;
}
int main()
{
auto res = compute(0);
if (!res)
{
std::cerr << "Caught error: " << res.err << std::endl;
return 1;
}
std::cout << "Value: " << res.unwrap_val() << std::endl;
return 0;
}Logging & Debugging
| Function | Description |
|---|---|
zlog_init(path, level) |
Initializes logging to a file (optional) and sets min level. |
zlog_set_level(level) |
Sets the minimum logging level at runtime. |
log_info(...) |
Logs an info message (White). |
log_warn(...) |
Logs a warning message (Yellow). |
log_error(...) |
Logs an error message (Red). |
log_debug(...) |
Logs a debug message (Cyan, if level permits). |
log_trace(...) |
Logs a trace message (Blue, if level permits). |
Data Structures
| Function / Macro | Description |
|---|---|
zerr |
Base error struct containing code, message, file, line, and trace info. |
zres |
Standard void result type (contains is_ok and zerr). |
ResInt |
Typed result carrying an int value or an error. |
ResPtr |
Typed result carrying a void* value or an error. |
Creation & Manipulation
| Type | Description |
|---|---|
zerr_create(code, msg) |
Creates a new error with current file/line context. |
zerr_errno(code, msg) |
Creates a new error, appending the string description of errno. |
zerr_wrap(e, fmt, ...) |
Wraps an existing error with a new context message. |
zerr_print(e) |
Prints a stylized error report to stderr. |
zerr_panic(msg) |
Prints a panic message and aborts the program. |
Flow Control
| Function | Description |
|---|---|
check(expr) |
Propagates error for functions returning zres or typed results. |
check_into(Type, expr) |
Propagates error, converting it to a Type result. |
check_wrap(expr, fmt) |
Propagates error with a wrapping context message. |
try(expr) |
Evaluates expr. If error, returns it. Else returns the unwrapped value. |
try_into(Type, expr) |
Same as try, but converts the error return type. |
expect(expr, msg) |
Evaluates expr. If error, panics with msg. |
ensure(cond, code, msg) |
Returns an error if cond is false. |
run(expr) |
Executes entry point function (returning zres), printing errors on failure. |
Namespace z_log
| Macro | Description |
|---|---|
z_log::info(fmt, ...) |
Logs an info message using C-style formatting. |
z_log::warn(fmt, ...) |
Logs a warning message using C-style formatting. |
z_log::error(fmt, ...) |
Logs an error message using C-style formatting. |
z_log::info(str) |
Logs a std::string as info. |
z_log::error(str) |
Logs a std::string as error. |
Class z_error::result
| Function | Description |
|---|---|
result(val) |
Constructors for creating a success result (move or copy). |
result(err) |
Constructors for creating a failure result from zerr or zres. |
ok() |
Returns true if the result contains a value (success). |
unwrap_val() |
Returns the contained value or panics if it is an error. |
err |
Public member accessing the underlying zerr struct (valid only if !ok()). |
operator bool() |
Implicit conversion to boolean (true = success). |
Shortcuts
| Method | Description |
|---|---|
ztry(expr) |
Statement expression that unwraps a result<T> or returns the error immediately. |
Define these macros before including zerror.h to modify behavior:
| Macro | Description |
|---|---|
ZERROR_IMPLEMENTATION |
Define in exactly one .c or .cpp file to generate logic. |
ZERROR_SHORT_NAMES |
Enables shorter aliases (for example, try, check, ensure). |
ZERROR_DEBUG |
Enables hardware traps/breakpoints at the exact moment an error is created. |
ZERROR_ENABLE_TRACE |
Enables the collection of propagation traces. |
ZERROR_NO_COLOR |
Disables ANSI color codes in zerr_print. |
ZERROR_PANIC_ACTION |
Define to override the default abort() behavior. |
zerror.h uses an internal thread-local ring buffer to handle error messages. This allows you to return formatted error messages from functions without worrying about malloc or free.
The common library (zcommon.h block) also allows you to override the standard allocators used by the system.