尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【Bug已解决】C API memory leak Asan 解决方案
【Bug已解决】C API memory leak Asan 解决方案一、现象长什么样用 ONNX Runtime 的 C API不是 Python/Java 高层封装写程序并用 AddressSanitizer (ASAN) 编译运行ASAN 在退出时报告内存泄漏指向 C API 分配的某块内存没有被释放12345ERROR: LeakSanitizer: detected memory leak Direct leak of 1024 byte(s) in 1 object(s) allocated from: #0 ort::... Allocator::Alloc #1 OrtGetApiBase / Ort::...::... (C API 内部)最小触发C API#include onnxruntime/core/session/onnxruntime_c_api.h int main() { OrtEnv* env NULL; OrtCreateEnv(ORT_LOGGING_LEVEL_WARNING, demo, env); // ... 用 C API 创建 session、跑推理 ... OrtReleaseEnv(env); // 必须配对的 Release 调用 return 0; } // ASAN 报泄漏某块 C API 内部分配没被对应 Release 释放注意程序能跑出正确结果只是 ASAN 抓到泄漏。这是C API 的资源释放契约问题——分配的每块内存都要有对应的OrtReleaseXxx调用漏一个就泄漏。二、背景ONNX Runtime 的 C API 遵循“谁分配、谁释放、用显式 Release 函数”的契约。C API 里几乎所有不透明句柄OrtEnv、OrtSession、OrtValue、OrtRunOptions、OrtMemoryInfo、OrtAllocator等都是内部在堆上分配的调用方拿到指针后必须在不用时调用对应的OrtReleaseXxx归还。ASAN 会在程序退出时扫描所有未释放的堆块报告泄漏。常见的泄漏来源忘记配对 Release创建了OrtValue/OrtRunOptions/OrtMemoryInfo却没OrtReleaseValue/OrtReleaseRunOptions/OrtReleaseMemoryInfo。API 本身漏释放某些 C API 函数在内部Alloc了一块比如返回字符串、返回数组但没有提供对应的 Release 函数或文档没说要释放调用方无从释放 - 泄漏在 API 侧。异常路径提前返回C 封装C API用了 RAII但裸 C 调用里中间出错goto/提前 return跳过了后面的 Release。长期持有不释放循环里反复创建OrtValue但不释放累积泄漏。三、根因根因是C API 分配的某些资源没有对应的 Release 调用被发起要么调用方漏写要么 API 没提供 ReleaseASAN 退出时抓到未释放堆块调用方漏配对 Release最常见的泄漏——OrtCreateXxx了但忘了OrtReleaseXxx或错误/提前返回路径跳过了 Release。API 侧缺 Release 入口某些函数返回的堆内存如OrtGetErrorMessage返回的字符串、Ort::...某些数组需要特定 Release 释放但 API 没暴露或文档不清调用方释放不了 - 泄漏在 API 实现里。C 封装与裸 C 混用用了 C API 的 RAII 对象但中间又手动new/取了裸指针没管。不是推理错结果正确只是资源释放契约被破坏ASAN 抓泄漏。所以这不是数值错而是C API 资源释放契约没被完整履行漏 Release 或 API 不给 Release。四、最小可运行复现下面用 C 标准库模拟“Alloc 了但没 Release - ASAN 报泄漏”的精简模型#include stdlib.h #include stdio.h // 模拟 ORT C APIAlloc 必须配对 Release void* OrtAlloc(size_t n) { return malloc(n); } void OrtRelease(void* p) { free(p); } int main() { void* a OrtAlloc(1024); // 分配 // 忘记 OrtRelease(a); // -- 漏了配对 Release - 泄漏 (void)a; return 0; } // 用 clang -fsanitizeaddress 编译运行 - LeakSanitizer 报 1024 字节泄漏clang -fsanitizeaddress -g demo.c -o demo ./demo会报Direct leak of 1024 byte(s)正是“Alloc 不 Release”的精简复现。把OrtRelease(a)加回去泄漏就消失。五、解决方案第一层最小直接修复最小修复给每个OrtCreateXxx/OrtAlloc配对的OrtReleaseXxx覆盖所有返回路径包括错误/提前返回。推荐用 C RAII 封装避免手漏#include onnxruntime/core/session/onnxruntime_cxx_api.h int main() { Ort::Env env(ORT_LOGGING_LEVEL_WARNING, demo); // RAII析构自动 Release Ort::SessionOptions so; Ort::Session session(env, model.onnx, so); // RAII // 用 C API 的 Ort::ValueRAII管理输入输出析构自动释放 Ort::MemoryInfo mi(Cpu, OrtDeviceAllocator, 0, OrtMemTypeDefault); // 所有 Ort:: 对象离开作用域自动 Release杜绝漏配 return 0; }如果必须用裸 C API用goto cleanup/defer模式确保每条路径都 ReleaseOrtValue* val NULL; OrtStatus* st OrtCreateValue(..., val); if (st) { /* 处理错误并 goto cleanup */ } // ... 使用 val ... cleanup: if (val) OrtReleaseValue(val); // 所有路径都释放 if (st) OrtReleaseStatus(st);这一层立刻消除大多数调用方泄漏。六、解决方案第二层结构性改进把“每个 C API 句柄的配对 Release 契约”收口成唯一的配置对象OrtCApiAsanLeakPolicy代码评审与静态检查读它from dataclasses import dataclass, field from typing import Tuple, Dict dataclass(frozenTrue) class OrtCApiAsanLeakPolicy: C API 资源释放契约的单一事实来源。 # 句柄 - 必须配对的 Release 函数全量映射 release_map: Tuple[Tuple[str, str], ...] ( (OrtEnv, OrtReleaseEnv), (OrtSession, OrtReleaseSession), (OrtValue, OrtReleaseValue), (OrtRunOptions, OrtReleaseRunOptions), (OrtMemoryInfo, OrtReleaseMemoryInfo), (OrtAllocator, OrtReleaseAllocator), (OrtStatus, OrtReleaseStatus), ) # 是否要求优先用 C RAII 封装避免手漏 prefer_raii: bool True # ASAN 构建下必须零泄漏 require_zero_leak_under_asan: bool True def paired_release(self, handle: str) - str: m dict(self.release_map) return m.get(handle, UNKNOWN) def describe(self) - str: return 每个 OrtCreateXxx 必须配对 OrtReleaseXxx优先 RAIIASAN 零泄漏 POLICY OrtCApiAsanLeakPolicy() def check_release(handle: str, policy: OrtCApiAsanLeakPolicy POLICY) - str: return policy.paired_release(handle)所有 C API 使用与评审读同一份POLICY释放契约被固化漏配一眼可见。七、解决方案第三层断言 / CI 守护把“C API 无泄漏ASAN 通过”做成断言。下面用 pytest 风格守护用模拟对象验证配对import pytest def test_every_handle_has_release(policy): for handle, rel in policy.release_map: assert rel.startswith(OrtRelease) assert rel ! UNKNOWN def test_prefer_raii(policy): assert policy.prefer_raii is True def test_asan_zero_leak_required(policy): assert policy.require_zero_leak_under_asan is True def test_release_pairing_complete(): handles [OrtEnv, OrtSession, OrtValue, OrtRunOptions] for h in handles: assert check_release(h) fOrtRelease{h[3:]} # OrtEnv-OrtReleaseEnv这四组断言锁住(1) 每个句柄都有 Release(2) 优先 RAII(3) ASAN 零泄漏要求(4) 配对完整。CI 跑通即代表释放契约被守护。八、排查清单遇到 C API 程序 ASAN 报泄漏看泄漏栈指向哪个 Alloc定位是哪个 Ort 句柄没释放。查配对 Release有没有OrtReleaseXxx对应每个OrtCreateXxx/OrtAlloc。查所有返回路径错误/提前 return 路径是不是也 Release 了。优先改 C RAII用Ort::封装析构自动释放避免手漏。API 侧泄漏若泄漏在 ORT 内部没提供 Release向 ORT 提 issue 补 Release。统一策略对象用OrtCApiAsanLeakPolicy固化释放映射。CI 守护ASAN 构建必须零泄漏断言配对完整。九、小结C API memory leak Asan的根因是ONNX Runtime 的 C API 遵循“分配必须配对 Release”的契约但使用方漏写OrtReleaseXxx尤其错误/提前返回路径或某些 API 内部分配的内存没有对应的 Release 入口ASAN 在退出时抓到未释放堆块。最小修复是给每个OrtCreateXxx配对的OrtReleaseXxx、覆盖所有返回路径优先用 C RAII 封装Ort::自动释放结构性改进是用唯一的OrtCApiAsanLeakPolicy固化句柄-Release 映射CI 用四组断言守护“每句柄有 Release、优先 RAII、ASAN 零泄漏、配对完整”。记住C API 里每个 Alloc 都要有 Release缺一个 ASAN 就报泄漏RAII 是最省心的防线。
RELATED

相关推荐

3步掌握OpenSpec自定义配置:从快速诊断到深度定制

3步掌握OpenSpec自定义配置:从快速诊断到深度定制

3步掌握OpenSpec自定义配置:从快速诊断到深度定制 【免费下载链接】OpenSpec Spec-driven development (SDD) for AI coding assistants. 项目地址: https://gitcode.com/GitHub_Trending/op/OpenSpec OpenSpec是一款面向AI编码助手的规范驱动开发工具&#…

📅 2026/10/4 10:03:47
Pixelle-Video:如何用AI技术让视频创作变得像写一句话那么简单?

Pixelle-Video:如何用AI技术让视频创作变得像写一句话那么简单?

Pixelle-Video:如何用AI技术让视频创作变得像写一句话那么简单? 【免费下载链接】Pixelle-Video 🚀 AI 全自动短视频引擎 | AI Fully Automated Short Video Engine 项目地址: https://gitcode.com/GitHub_Trending/pi/Pixelle-Video …

📅 2026/9/14 21:09:30
钢丝高频退火设备网站建设:如何打造一家有温度且专业的工业制造品牌官网

钢丝高频退火设备网站建设:如何打造一家有温度且专业的工业制造品牌官网

很多人问,咱们搞实业的,天天泡在车间里,跟铜铁打交道,怎么还有心思去琢磨什么网站、什么SEO、什么用户体验这些听起来就很“虚”的东西?说实话,刚开始我也这么想。我觉得产品好就行,只要钢丝硬、退火均匀、能耗低,客户自然会找上门来,靠的都是老客户带新客户,靠的是口…

📅 2026/9/23 3:02:42
MORE NEWS

更多资讯

📰

InnoDB存储结构:记录在页里,为什么不从第一行一直找?

我最开始整理 InnoDB,列了很多问题:没建索引怎么存?页里有什么?记录为什么有 next_record?长字符串放哪里?问题不少,却没有把它们连接起来。 这次先抓一个问题:索引已经找到某个叶子…

📰

Moodle 主题图标尺寸控制指南:从 `{{pix}}` 模板助手到 `icon-size` 工具类

教育后端前端 【免费下载链接】moodle Moodle - the worlds open source learning platform 项目地址: https://gitcode.com/gh_mirrors/mo/moodle 点击查看 免费下载 导读:本文以 public/admin/tool/componentlibrary/content/moodle/themes/iconsizes…

📰

Rufus 3.22 还能做 Windows 7 启动盘吗?版本边界一查便知

Rufus 3.22 还能做 Windows 7 启动盘吗?版本边界一查便知 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus Rufus 是 USB 启动盘格式化工具,核心能力是格式化 U 盘并写入 IS…

📰

cppcheck 的 uselessCallsConstructor 检查:识别容器自我切片赋值的低效构造调用

开发工具静态分析代码质量质量保障 【免费下载链接】cppcheck static analysis of C/C code 项目地址: https://gitcode.com/gh_mirrors/cpp/cppcheck 点击查看 免费下载 导读 uselessCallsConstructor 是 C 静态分析工具 cppcheck 在 STL 相关检查(Ch…

📰

uBlock Origin:免费开源的轻量广告拦截插件

uBlock Origin:免费开源的轻量广告拦截插件 【免费下载链接】uBlock uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean. 项目地址: https://gitcode.com/GitHub_Trending/ub/uBlock 点开一个新闻页,标题还没读完&a…

📰

LinkSwift 网盘直链下载教程:8 大网盘免费解析真实直链

LinkSwift 网盘直链下载教程:8 大网盘免费解析真实直链 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬