编码规范
本文档定义 Runtime 仓代码实现时应遵守的统一编码规范。
文档结构:
一、通用 C/C++ 编码规范适用于 Runtime 仓的所有 C/C++ 代码,包括源码和 UT 代码。二、Runtime 约束性规范主要适用于src/、include/、pkg_inc/、cmake/及其他非测试代码;审查或编写 UT 代码时,只在确实涉及相关场景时参考。
一、通用 C/C++ 编码规范
规则 1:禁止硬编码敏感信息、使用禁用敏感词
- 源码中禁止硬编码明文密码、密钥等高级别敏感数据。
- 需要彻底清理历史遗留的废弃账号、密码和用途不明的敏感配置。
- 用途不明、语义含糊的大数组或可读性差的隐藏数据定义,容易被质疑为后门实现,应避免。
- 代码或者配置中硬编码公网 IP、域名、邮箱地址以及容易引起误解的敏感词时,必须能说明合理用途;尤其不能出现指向华为或中国的可疑公网地址。
规则 2:外部数据作为数组索引或者指针偏移时,必须确保访问范围合法
- 数组索引、内存偏移、长度和容量若直接由外部控制,必须先做严格范围校验,防止越界访问。
规则 3:整数之间运算时必须严格检查,确保不会出现溢出、反转、除 0
- 若整数运算结果会参与内存申请、偏移计算、循环边界或拷贝长度,必须评估溢出、反转、截断和除零风险。
规则 4:资源管理和生命周期必须清晰,获取与释放必须成对
- 文件句柄、内存以及 device、driver、context、stream、event、notify 等句柄,都必须在生命周期结束后及时释放。
- 异常分支和早返回路径不能遗漏清理动作。
- 资源释放后应立即赋予明确新值,避免悬空指针和重复释放。
- 内存、锁、句柄等资源的获取与释放必须成对出现;优先使用 RAII 管理资源生命周期。
规则 5:内存申请前必须判断大小,申请后必须校验是否成功
- 申请大小可能来自外部输入,必须检查合法性,不能申请 0 长度内存。
- 外置 allocator 需要同时校验返回的结构体指针以及结构体内部
data指针是否有效。 - 内存申请后应评估是否需要初始化,避免读取未初始化内存。
规则 6:外部输入、空指针、数组下标和循环边界必须先校验
- 用户参数、driver 返回值、配置文件、环境变量等外部输入,进入关键逻辑前都必须完成合法性校验。
- 解引用前必须确认指针有效。
- 数组下标、长度和循环边界必须位于合法范围内。
规则 7:错误处理必须完整,禁止吞错
- 调用链上的错误返回值必须被正确传播,不能静默吞掉错误。
- 返回的错误码必须语义准确。
- 错误路径上已经申请的资源必须同步释放。
- 错误处理宏必须使用正确,避免出现“记录了日志但没有收口”或“直接返回但缺少上下文”的情况。
规则 8:缓冲区、内存操作和对象生命周期必须满足基础安全约束
- 数组或缓冲区访问必须避免越界。
new/delete、malloc/free、new[]/delete[]必须严格配对,禁止混用。- 使用
new(std::nothrow)时必须判空;使用普通new时不要再做nullptr判空。 - 禁止返回栈空间地址。
- 释放对象前,应明确对象内部成员指针的处理策略,避免二次释放或悬空引用。
规则 9:并发场景必须显式保证线程安全
- 多线程场景下的共享数据必须有明确保护策略,避免竞态和可见性问题。
- 普通锁禁止随意嵌套,避免死锁风险。
- 涉及线程上下文切换、异步任务或回调时,必须明确时序关系和资源有效期。
规则 10:不要编写依赖表达式求值顺序或隐式优先级的代码
- 类似
func(a++, a)的写法会依赖未指定的求值顺序,属于未定义行为,必须避免。 - 复杂表达式应使用括号明确运算优先级,避免依赖默认优先顺序。
规则 11:代码风格和提交内容必须保持整洁一致
- 变更代码必须符合仓库
.clang-format配置。 - 命名必须符合项目惯例:函数名使用大驼峰,私有方法允许尾部下划线;变量名使用小驼峰;常量和宏使用全大写下划线;类名使用大驼峰。
- 新文件必须包含华为 CANN Open Software License 版权头。
- include 顺序必须符合项目惯例。
- 提交中不得残留调试代码、注释掉的代码、未使用的 include 或变量。
- 新增文件权限必须合理,源码应为 644,可执行脚本应为 755。
二、Runtime 约束性规范
规则 12:对外开放接口的预留参数要有严格校验,防止后续版本启用时出现兼容性问题
- 预留参数必须强制用户传入无效值,否则后续启用时容易引入兼容性问题。
- 数值类预留参数的无效值一般为
0。 - 指针类预留参数的无效值一般为
nullptr。
规则 13:对外接口中表达内存长度的返回值或参数,应优先使用 size_t
- 涉及内存长度、缓冲区大小、字节数等语义时,应优先使用
size_t,避免 32 位长度表达不足的问题。
规则 14:修改对外开放接口时,必须严格确保 API 和 ABI 兼容
include/、include/external/acl/和对外发布头文件边界上的修改,都必须严格评估 API/ABI 兼容性。- 对外头文件的公开接口中禁止使用
std::string作为 ABI 边界类型,应使用仓内兼容替代方案。 - 新增或修改结构体时要考虑保留字段和后向兼容。
- 废弃接口应优先做兼容标记,而不是直接删除。
规则 15:禁止在公共路径中硬编码芯片、平台或驱动能力分支
- 公共逻辑应优先通过能力查询、配置注册或平台隔离目录处理差异。
- 确需区分平台的逻辑,应收敛在
config/、平台子目录或明确的能力适配层中。
规则 16:禁止在加载/执行热路径中随意增加 EVENT/TRACE 打印
- 热路径海量日志会引入明显性能抖动和 IO 压力。
- 加载/执行热路径中禁止新增默认开启的 EVENT/TRACE 级别日志。
- 可以增加默认关闭的 DEBUG/INFO 日志,但需要评估开关策略和字符串开销。
- ERROR 日志仅用于真实异常,不可用于正常分支。
规则 17:调用其他组件提供的、需要 Runtime 传入资源的接口时,必须提前确认资源生命周期约束
- 设计和编码阶段都要明确跨组件接口是否持有传入指针、何时复用、何时释放。
规则 18:对执行顺序敏感的逻辑,禁止依赖无序容器遍历结果
- 如果容器遍历顺序会影响任务、事件、通知、回调注册或资源初始化顺序,禁止直接依赖
std::unordered_map等无序容器的遍历结果。 - 需要稳定顺序时优先使用有序容器或显式排序。
- 不要使用进程内地址值作为顺序依据。
规则 19:禁止单例模式在头文件中以内联方式实现
- 头文件内联单例在多编译单元、动态库和
dlopen场景下可能带来多实例、析构时序和崩溃问题。
规则 20:禁止新增未公开的对外接口边界
- 新增对外接口时,只能放在明确的公开边界头文件中;不要通过内部头文件或内部符号对外泄露能力。
规则 21:禁止在静态对象或全局对象析构函数里做跨 SO 的函数调用
- 跨动态库析构顺序不可预测,极易导致悬空引用、异常终止和崩溃。
- 典型风险包括:依赖的 SO 已卸载;
shared_ptr析构触发虚析构函数,但实际类型所在 SO 已失效;程序退出阶段其他线程仍在访问静态对象。 - 推荐做法是把清理工作放到显式的
Finalize()或等价接口中,在运行期完成清理,析构阶段保持空操作或仅做本地对象回收。
规则 22:实现逻辑必须与设计和接口约束保持一致
- 编码前应明确变更对应的设计意图、接口约束和场景预期。
- 实现中不得遗漏分支、边界条件或异常路径。
- 正常流程、异常流程和边界场景的处理方式必须保持一致。
规则 23:编写日志时必须保证级别、内容和热路径开销合理
RT_LOG_ERROR仅用于不可恢复错误,RT_LOG_WARNING用于功能降级或非致命异常,RT_LOG_INFO用于关键操作节点,RT_LOG_DEBUG用于调试信息。- 日志内容必须包含足够上下文,并避免打印敏感信息。
- 格式化字符串必须与参数类型匹配。
- 日志内容中不得硬编码函数名,不得出现英文拼写错误。
- 热路径不得引入高频日志。
- 项目内错误日志宏必须使用正确,例如
COND_RETURN_ERROR_MSG_INNER、RecordErrorLog等。
规则 24:修改公共接口时必须同步满足兼容性要求
- 修改
include/目录下头文件时,必须按向后兼容原则设计变更。 - 公共 API 函数签名不得发生 breaking change,除非该变更已被明确接受并完成迁移设计。
- 接口废弃应通过标记完成,而不是直接删除。
- 枚举定义不得随意引入
XX_MAX或影响多版本匹配兼容性。 pkg_inc/runtime/runtime不得误新增内容,确需新增时必须先确认是否应改为其它公开边界。
规则 25:修改公开接口和错误码时必须同步更新文档
- 修改
include/external/acl/acl_rt.h时,必须在同一次变更中同步更新对应docs/文档。 - 修改
include/external/acl/error_codes/rt_error_codes.h时,必须在同一次变更中同步更新docs/03_api_ref/25_数据类型及其操作接口.md。
规则 26:实现时必须遵守既有软件架构和构建边界
src/runtime中非api目录不应调用api目录的方法,例如feature目录不应访问Api::Instance。- 编写实现时必须保持既有目录边界、平台隔离边界和组件职责边界清晰。
src/runtime目录仅允许使用STATIC_RT_LIB、RUNTIME_API、CFG_DEV_PLATFORM_PC及编译器内置宏;禁止新增其他编译宏。