CANN opbase 中 aclDestroyIntArray 详解:aclIntArray 资源释放接口的原型、源码实现与最佳实践
2026/9/18 14:14:21 网站建设 项目流程

CANN opbase 中 aclDestroyIntArray 详解:aclIntArray 资源释放接口的原型、源码实现与最佳实践

【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase

在 CANN 算子库基础框架(opbase)的 aclnn 单算子执行接口中,aclIntArray是承载整型序列(如 shape 维度、padding、strides 等)的核心参数容器。本篇以 aclDestroyIntArray 官方文档 为主体,完整继承其原型、参数与返回值说明,并结合 opbase 仓库源码(acl_op_api.cpp、acl_meta.h)深入剖析该接口的空指针处理、双重释放防护机制与返回码体系,帮助读者掌握 aclIntArray 的完整“创建—使用—销毁”生命周期管理,写出无内存泄漏、无悬垂指针的算子调用代码。

功能定位

根据官方文档,aclDestroyIntArray的功能是:销毁通过 aclCreateIntArray 接口创建的aclIntArray

从源码结构看,aclIntArray是一个不透明类型(opaque type)。acl_meta.h 中仅定义了:

typedef struct aclIntArray aclIntArray;

即调用方只能持有指向它的指针,无法也无需访问其内部成员。这与 aclCreateIntArray 文档 的表述一致:它是“框架定义的数组结构,用于管理和存储整型数据,使用时无需了解其内部实现”。正因为内存由框架内部分配(创建时把宿主侧int64_t数组拷贝aclIntArray),销毁也必须且只能通过aclDestroyIntArray完成,二者构成严格配对的资源生命周期 API。

函数原型

aclnnStatus aclDestroyIntArray(const aclIntArray *array)

接口声明位于公共头文件 acl_meta.h:

ACL_FUNC_VISIBILITY aclnnStatus aclDestroyIntArray(const aclIntArray* array);

原型要点:

  • 入参为const aclIntArray *指针。注意这里传的是“指向常量的指针”(表示销毁操作不会修改对象内容),而非const aclIntArray **,即该接口不会将传入指针置空,调用方无需(也不能)依赖“销毁后指针自动变 nullptr”的行为;
  • 返回类型为aclnnStatus,取值 0(ACLNN_SUCCESS)表示成功,非 0 表示失败,具体返回码参见 公共接口返回码。

参数说明

参数名输入/输出说明
array输入需要销毁的aclIntArray。该指针应来自此前aclCreateIntArray的成功返回

使用前提约束(来自配对接口 aclCreateIntArray 的 Restrictions 章节,对销毁侧同样成立):

  • 本接口必须与aclCreateIntArray成对使用,分别负责aclIntArray的创建与销毁;
  • 若需查询数组长度,应使用 aclGetIntArraySize 接口,且必须在销毁前调用——销毁后指针即失效,任何再访问(包括aclGetIntArraySize)都属于未定义行为。

返回值说明

返回 0 表示成功,返回其他值表示失败。opbase aclnn 公共接口的完整返回码定义见 common_api_return_codes.md:

错误码说明
ACLNN_SUCCESS0成功
ACLNN_ERR_PARAM_NULLPTR161001参数校验失败,参数中包含非法nullptr
ACLNN_ERR_PARAM_INVALID161002参数校验失败,例如输入数据类型不满足推导要求
ACLNN_ERR_RUNTIME_ERROR361001调用 NPU Runtime API 时发生异常
ACLNN_ERR_INNER_XXX561xxx内部 API 异常,常见内部异常场景:
561101(ACLNN_ERR_INNER_CREATE_EXECUTOR):创建aclOpExecutor失败
561102(ACLNN_ERR_INNER_NOT_TRANS_EXECUTOR):内部未调用uniqueExecutorReleaseTo
561103(ACLNN_ERR_INNER_NULLPTR):aclnn API 中出现空指针错误

需要获取可读错误消息时,文档建议调用 Runtime APIs 中的aclGetRecentErrMsg获取错误描述,再据此排查。

约束说明

官方文档标注本接口无额外约束(None),即对调用频率、线程环境等没有额外限制。但从源码实现可以读出两条隐含的使用规则(见下节),工程上应遵守:

  1. 只销毁由aclCreateIntArray成功返回的指针,不要传入野指针;
  2. 同一个aclIntArray只销毁一次。

源码实现剖析

aclDestroyIntArray的完整实现位于 acl_op_api.cpp:

aclnnStatus aclDestroyIntArray(const aclIntArray* array) { if (array == nullptr) { return OK; } if (unlikely(op::internal::IsAclnnDebugEnabled()) && op::internal::CheckDoubleFree(const_cast<aclIntArray*>(array))) { OP_LOGW("Possible double-free at addr %p.", static_cast<const void*>(array)); } delete array; return OK; }

这段实现比“原型 + 返回码表格”多透露了三个重要事实:

1. 空指针是安全的,且直接返回成功。array == nullptr时函数直接return OK。也就是说aclDestroyIntArray(nullptr)返回 0,不会触发ACLNN_ERR_PARAM_NULLPTR。这一行为与销毁族其他接口(aclDestroyFloatArray、aclDestroyBoolArray 等)完全一致,使得“先判空再销毁”可以简化为“无条件调用销毁”,是典型的幂等式资源释放设计。

2. 双重释放检测受调试开关控制。op::internal::IsAclnnDebugEnabled()为真时(该开关由 op_dfx.cpp 中的原子标志g_aclnnDebugEnabled承载,可从源码结构看由调试配置打开),接口会调用 CheckDoubleFree(声明于 bridge_pool.h)检查该地址是否仍处于活跃内存块状态。若检测到“已被释放过一次”的地址再次被销毁,仅打印Possible double-free at addr %p.警告日志,并不阻断后续delete——这是一个诊断性检查而非运行时防护。因此生产代码中仍必须自行保证“只销毁一次”,该机制只是在调试期帮你定位问题。

3. 当前实现恒返回 0。从源码路径看,aclDestroyIntArray无论入参是否为空,最终都执行return OK,不会返回 161001/161002 等错误码。文档中“返回其他值表示失败”是 aclnn 公共接口返回码的通用契约描述;对当前版本的该接口而言,只要调用不崩溃,返回值恒为 0。工程上仍建议按契约检查返回值,以便兼容后续实现变化。

调用示例

官方文档的示例指引参见 aclCreateIntArray 的调用示例。将其完整继承并补充注释如下,展示aclIntArray从创建到销毁的完整生命周期(示例仅供参考,非直接可运行代码,aclxxXxx为具体算子的 aclnn 接口占位):

// 1. 准备宿主侧整型数据,例如 shape 维度 {1, 1, 2, 3} std::vector<int64_t> sizeData = {1, 1, 2, 3}; // 2. 创建 aclIntArray:value 为宿主侧 int64_t 指针,内容会被拷贝进 aclIntArray, // 因此创建成功后 sizeData 可独立于 aclIntArray 释放 aclIntArray *size = aclCreateIntArray(sizeData.data(), sizeData.size()); // 3. 作为单算子 API 的输入参数使用(以获取 workspace size 并执行算子为例) auto ret = aclxxXxxGetWorkspaceSize(srcTensor, size, ..., outTensor, ..., &workspaceSize, &executor); ret = aclxxXxx(...); // ... // 4. 销毁 aclIntArray:与创建配对调用,销毁后 size 指针立即失效 ret = aclDestroyIntArray(size);

要点提示:

  • aclCreateIntArray返回nullptr时(例如创建过程异常,参见 acl_op_api.cpp 中失败分支打印aclCreateIntArray error.日志后返回nullptr),后续直接使用会崩溃,应先判空;而aclDestroyIntArray(nullptr)本身安全,可放心兜底调用;
  • 销毁时机应在最后一次使用该数组之后,典型位置是算子执行完成、workspace 释放附近;
  • 若同时创建了aclTensoraclScalaraclFloatArray等多种参数容器,销毁顺序无强制要求,但建议按“谁创建后使用、谁先释放”的原则统一收口,避免遗漏。

相关接口与测试佐证

  • 同族销毁接口行为一致,可对照阅读:aclDestroyFloatArray、aclDestroyBoolArray、aclDestroyTensor、aclDestroyScalar,实现均在 acl_op_api.cpp 中;
  • 数组尺寸查询:aclGetIntArraySize;
  • 接口总览与分类:aclnn API 列表、common_api_list.md;
  • 单元测试中大量用例会创建并销毁aclIntArray等参数容器,例如 test_acl_op_api.cpp、test_tilingctx_builder.cpp 与集成测试 st/composite_op/test_acl_op_api.cpp,可作为“创建—使用—销毁”闭环的参考实现;
  • 中文文档版本见 aclDestroyIntArray.md。

小结

aclDestroyIntArray是 aclnn 单算子执行链路上aclIntArray资源的生命周期终点:原型为aclnnStatus aclDestroyIntArray(const aclIntArray *array),参数仅一个待销毁的aclIntArray指针,返回 0 表示成功,无额外调用约束。结合 acl_op_api.cpp 源码可以确认:空指针入参安全且返回成功、销毁时恒返回OK、调试模式下具备双重释放告警能力。将其与 aclCreateIntArray 严格配对使用、并在销毁前完成最后一次数据访问(如aclGetIntArraySize),即可在保证内存安全的前提下完成整型参数容器的完整管理。

【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询