错误码一览

llbc 使用统一的整型错误码体系。调用失败后,通过 LLBC_GetLastError() 取得最近一次错误码, 通过 LLBC_StrError(no) 或 LLBC_FormatLastError() 取得可读描述字符串。 绝大多数 API 遵守”返回 LLBC_OK(0) 成功,返回 LLBC_FAILED(-1) 失败”约定。

错误码结构

每个错误码是一个 32 位整数,按位段分层编码:

位 31-30  Sev   严重级别  00=成功 01=信息 10=警告 11=错误
位 29     C     用户自定义标志
位 28-20  —     保留(必须为 0)
位 19-16  Type  错误来源  0=llbc库 1=C库 2=OS API 3=网络API 4=getaddrinfo
位 15-0   No    错误编号

公开宏 LLBC_ERROR_* 已将上述字段组合为完整值,直接用于比较即可。

llbc 库内置错误码

下表列出 llbc/include/llbc/common/Errno.h 中全部内置错误码(__LLBC_ERROR_* 为内部原始编号,不在公开 API 中直接使用)。

错误码宏 含义
LLBC_ERROR_SUCCESS 成功(值为 0)
LLBC_ERROR_UNKNOWN 未知错误
LLBC_ERROR_CLIB C 标准库调用失败(子错误见 errno)
LLBC_ERROR_OSAPI 操作系统 API 调用失败(仅 Windows,子错误见 GetLastError())
LLBC_ERROR_NETAPI 网络 API 调用失败(仅 Windows WSA,子错误见 WSAGetLastError())
LLBC_ERROR_GAI getaddrinfo() 调用失败(子错误见 LLBC_GetSubErrorNo())
LLBC_ERROR_ARG 参数错误
LLBC_ERROR_NOT_IMPL 未实现
LLBC_ERROR_RANGE 范围越界
LLBC_ERROR_EXIST 对象/资源已存在
LLBC_ERROR_NOT_FOUND 对象/资源未找到
LLBC_ERROR_END 已到达末尾
LLBC_ERROR_LIMIT 达到数量/容量上限
LLBC_ERROR_NOT_INIT 尚未初始化
LLBC_ERROR_NOT_OPEN 尚未打开
LLBC_ERROR_INITED 已经初始化(重复初始化)
LLBC_ERROR_OPENED 已经打开(重复打开)
LLBC_ERROR_PERM 权限不足
LLBC_ERROR_TRUNCATED 数据被截断
LLBC_ERROR_INVALID 无效状态或无效数据
LLBC_ERROR_FORMAT 格式错误
LLBC_ERROR_TIMEOUTED 操作超时
LLBC_ERROR_BUSY 资源繁忙
LLBC_ERROR_REENTRY 不允许重入
LLBC_ERROR_NO_SUCH 无此内存/数据/资源
LLBC_ERROR_WBLOCK 操作会阻塞(would block)
LLBC_ERROR_AGAIN 请再试一次
LLBC_ERROR_PENDING 操作挂起/排队中
LLBC_ERROR_ILLEGAL 非法操作
LLBC_ERROR_ACCESS_DENY 访问被拒绝
LLBC_ERROR_REPEAT 重复操作
LLBC_ERROR_ENCODE 编码失败
LLBC_ERROR_DECODE 解码失败
LLBC_ERROR_COMPRESS 压缩失败
LLBC_ERROR_DECOMPRESS 解压失败
LLBC_ERROR_PACK 打包失败
LLBC_ERROR_UNPACK 解包失败
LLBC_ERROR_NOT_ALLOW 不允许该操作
LLBC_ERROR_COMP_INIT_FAILED Component 初始化失败
LLBC_ERROR_COMP_LATE_INIT_FAILED Component 延迟初始化失败
LLBC_ERROR_COMP_START_FAILED Component 启动失败
LLBC_ERROR_COMP_LATE_START_FAILED Component 延迟启动失败
LLBC_ERROR_WSA_SYSNOTREADY 底层网络子系统未就绪(仅 Windows)
LLBC_ERROR_WSA_VERNOTSUPPORTED 请求的 WinSock 版本不受支持(仅 Windows)
LLBC_ERROR_WSA_EINPROGRESS 阻塞式 WinSock 1.1 操作正在进行(仅 Windows)
LLBC_ERROR_WSA_EPROCLIM 已达 WinSock 实现支持的任务数上限(仅 Windows)
LLBC_ERROR_IS_LISTEN_SOCKET 指定 Socket 为监听 Socket
LLBC_ERROR_NOT_POOL_OBJECT 对象不是对象池对象
LLBC_ERROR_SESSION_SND_BUF_LIMIT Session 发送缓冲区达到上限
LLBC_ERROR_NOT_SUPPORT 不支持该操作
LLBC_ERROR_CANCELLED 操作已取消
LLBC_ERROR_APP_EARLY_START_FAILED 应用早期启动阶段失败
LLBC_ERROR_APP_START_FAILED 应用启动失败
LLBC_ERROR_TIMER_SCHEDULER_DESTROYING 定时器调度器正在销毁
LLBC_ERROR_TIMER_SCHEDULER_CANCELING_ALL 定时器调度器正在取消全部定时器
LLBC_ERROR_EVENT_MANAGER_PRE_FIRE_FAILED 事件管理器 pre-fire 失败
LLBC_ERROR_PARTIAL_PARSED 数据仅部分解析

常用错误处理模式

// 调用失败后读取错误
if (LLBC_FAILED == someApi())
{
    LLBC_PrintLn("failed: %s", LLBC_FormatLastError());
    // 或者:
    int err = LLBC_GetLastError();
    LLBC_PrintLn("errNo=%d desc=%s", err, LLBC_StrError(err));
}

带子错误码的系统错误

LLBC_ERROR_CLIB、LLBC_ERROR_OSAPI、LLBC_ERROR_NETAPI、LLBC_ERROR_GAI 这四个错误码在格式化时会携带子错误的可读描述。使用方式:

// C 库错误:先设 errno,再设 llbc 错误
errno = EINVAL;
LLBC_SetLastError(LLBC_ERROR_CLIB);
LLBC_PrintLn("%s", LLBC_FormatLastError());  // 输出 C 库错误描述

// getaddrinfo 错误:用子错误号传 gai 错误码
LLBC_SetLastError(LLBC_ERROR_GAI);
LLBC_SetSubErrorNo(EAI_NODATA);
LLBC_PrintLn("%s", LLBC_FormatLastError());  // 输出 gai_strerror 描述

自定义错误码

业务层可注册自定义错误码,通过 LLBC_BuildCustomErrno 宏构建合法编号:

// 注册
const int ERR_MY_LOGIC = LLBC_BuildCustomErrno(1001);
LLBC_AddCustomErrno(ERR_MY_LOGIC, "my business logic error");

// 使用
LLBC_SetLastError(ERR_MY_LOGIC);
LLBC_PrintLn("%s", LLBC_FormatLastError());  // "my business logic error"

// 注销(单个 / 全部)
LLBC_RemoveCustomErrno(ERR_MY_LOGIC);
LLBC_RemoveAllCustomErrnos();

LLBC_BuildCustomErrno 只取传入值的低 16 位,并强制设置 Sev=Error、Custom=1。 不同模块请自行划分自定义编号区间,避免冲突。

设置错误时附加自定义描述字符串

LLBC_SetLastError 接受可选的 customErrStr 参数,用于在标准描述之外附加上下文信息:

LLBC_SetLastError(LLBC_ERROR_FORMAT, "field 'userId' missing in packet");
LLBC_PrintLn("%s", LLBC_FormatLastError());
// 输出中包含 "field 'userId' missing in packet"

customErrStr 指针的生命周期必须覆盖 LLBC_FormatLastError() 调用,不要传入临时字符串字面量以外的栈变量。

下一步

参照