发布时间:2026/8/15 5:59:21
【Bug已解决】AddInitializerToGraph ownership-semantics change in #28123 breaks C API callers (Chromium W… 【Bug已解决】AddInitializerToGraph ownership-semantics change in #28123 breaks C API callers (Chromium WebNN crash) 解决方案一、现象长什么样PR #28123 修改了AddInitializerToGraph这个内部函数的所有权语义ownership semantics后依赖它的C API 调用方尤其是 Chromium 里的 WebNN 实现在运行期崩溃# Chromium WebNN 调用 ORT C API 后崩溃 crash: double-free / use-after-free in AddInitializerToGraph # 或 ASAN: heap-use-after-free when WebNN releases the graph after AddInitializerToGraph具体表现崩溃只在C API 调用方Chromium WebNN出现ORT 自己的 C 测试可能不崩因为内部调用知道新语义。崩溃类型是内存安全类double free、use-after-free——典型的“所有权契约变了但调用方还按旧契约用”。时序上WebNN 建图时多次调用AddInitializerToGraph加权重建完释放图时崩。只有合进 #28123 之后的版本才崩回退该 PR 即恢复。关键特征函数改了“谁拥有这块内存、谁来释放”的契约但没同步给 C API 调用方导致调用方按旧契约释放了本不该它释放或已被移动的内存 → 内存安全崩溃。二、背景AddInitializerToGraph的作用是把一个权重张量initializer加进计算图。它接收一个张量比如TensorProto或Ort::Value把它登记到图的初始权重表里。“所有权语义”说的是这个函数接收的张量内存归谁旧语义调用方持有函数拷贝一份权重进图调用方传入的张量仍归调用方所有调用方自己负责释放。调用方可以复用/稍后释放互不干扰。新语义函数接管#28123 可能把它改成“移动/接管调用方传入的张量的所有权”为了避免拷贝、省内存即图建完后这块内存归图所有调用方不能再使用、也不能再释放它。问题在于 C API 的契约是稳定且对外承诺的。Chromium WebNN 作为 C API 调用方按旧语义写代码传完权重后自己Release掉那块Ort::Value。当 #28123 把语义悄悄改成“函数接管”Chromium 还去Release→double free图和 Chromium 都释放同一块或者反过来函数把内存移走Chromium 以为还在、继续读 →use-after-free。C API 的调用方跨进程/跨语言这里是 Chromium 的 C 通过 C ABI 调用 ORT 的 .so它们无法感知 ORT 内部的 PR 改动只能依赖 C API 头文件里声明的契约。契约变了却不改头文件/不通知崩溃必然发生。三、根因根因是#28123 改变了AddInitializerToGraph的所有权契约从“拷贝/调用方持有”变“移动/函数接管”但没有在 C API 层面保持契约稳定导致调用方按旧契约重复释放或误用已移交的内存所有权未通过 C API 显式声明C API 头里没写清楚“传入的Ort::Value是被拷贝还是被接管”调用方只能靠经验/旧行为假设PR 一改就错位。行为变更未向后兼容#28123 为了求性能改成移动语义但没保留旧行为如提供...Copy变体旧调用方直接踩坑。缺 ownership 文档/断言函数内部没断言“调用方是否还能用这块内存”double free / use-after-free 直到运行时才爆且只在外部调用方Chromium暴露。C API 是稳定契约对外 API 的语义变更必须版本化/明确否则跨模块调用方必崩。一句话内部 PR 改了张量所有权却没在稳定的 C API 契约上同步外部调用方按旧契约释放/使用内存 → 内存安全崩溃。四、最小可运行复现下面用 Python 模拟“所有权契约变化导致 double free / use-after-free”的机理from dataclasses import dataclass from typing import Optional dataclass class Buffer: data: list owner: str none freed: bool False def add_init_copy(graph_buffers: list, buf: Buffer) - None: 旧语义拷贝进图调用方仍持有 buf。 import copy graph_buffers.append(copy.deepcopy(buf)) # 图有自己的副本 # buf 仍归调用方 def add_init_take_ownership_buggy(graph_buffers: list, buf: Buffer) - None: 新语义buggy 暴露点接管 buf但没告知调用方。 buf.owner graph graph_buffers.append(buf) # 图持有同一份 # 调用方若不知情仍去释放 - double free # 场景Chromium 按旧契约传完自己释放 graph [] buf Buffer(data[1, 2, 3], ownercaller) add_init_copy(graph, buf) buf.freed True # 调用方释放自己的副本 - OK图是另一份 graph2 [] add_init_take_ownership_buggy(graph2, buf) # 图接管了 buf # 调用方不知情仍释放 - 图和调用方都以为自己拥有 - double free buf.freed True print(graph owns:, graph2[0].owner, caller freed:, buf.freed) # 若图析构时也 freedTrue - 重复释放这个模拟说明当函数“接管”了buf但调用方仍按旧契约释放就出现 double free 隐患——正是 Chromium WebNN 崩溃的来源。五、解决方案第一层最小直接修复最小修复是在 C API 层面恢复清晰且稳定的所有权契约要么保持“拷贝调用方持有”的旧语义要么显式提供“接管”的专门 API 并在头文件声明绝不在同一函数上静默改语义// C API 头修复片段契约明确写在注释里 // AddInitializerToGraphCopy: 拷贝 initializer 进图调用方保留并负责释放 value。 ORT_API_STATUS_IMPL(OrtApis::AddInitializerToGraphCopy, OrtSessionOptions* options, const char* name, const OrtValue* value); // AddInitializerToGraphTakeOwnership: 接管 value 所有权调用方此后不得再使用/释放。 ORT_API_STATUS_IMPL(OrtApis::AddInitializerToGraphTakeOwnership, OrtSessionOptions* options, const char* name, OrtValue* value); // 注意非 const语义是“移交”内部实现Status AddInitializerToGraphCopy(..., const OrtValue* value) { graph.AddInitializer(name, value-Copy()); // 拷贝调用方仍持有 return Status::OK(); } Status AddInitializerToGraphTakeOwnership(..., OrtValue* value) { graph.AddInitializer(name, std::move(*value)); // 接管 return Status::OK(); // 调用方不能再碰 value }Chromium WebNN 明确选...Copy保持旧行为崩溃消失想要省拷贝的新调用方用...TakeOwnership。契约显式、向后兼容。六、解决方案第二层结构性改进把“C API 张量/initializer 的所有权契约如何声明、变更如何向后兼容”收口成唯一的配置对象OrtCApiOwnershipPolicy所有 C API 包装读它from dataclasses import dataclass from typing import Tuple from enum import Enum class Ownership(Enum): COPY copy # 函数拷贝调用方持有 TAKE take # 函数接管调用方移交 BORROW borrow # 函数仅借用调用方持有 dataclass(frozenTrue) class OrtCApiOwnershipPolicy: C API 所有权契约的单一事实来源。 # 默认对外 API 保持 COPY 语义稳定、向后兼容 default_ownership: Ownership Ownership.COPY # 任何所有权变更必须提供显式命名的新 API不静默改旧 API forbid_silent_semantics_change: bool True # 契约必须在头文件注释里写明拷贝/接管/借用 document_ownership_in_header: bool True # 变更需版本化ORT_API_VERSION 递增 require_api_version_bump: bool True # 代码评审卡点 forbidden_patterns: Tuple[str, ...] ( change AddInitializerToGraph to take ownership silently, C API without ownership comment, ) def resolve(self, requested: Ownership) - Ownership: if requested is Ownership.TAKE and self.forbid_silent_semantics_change: # 接管必须通过显式命名的 API而非改默认 return Ownership.TAKE return self.default_ownership def describe(self) - str: return C API 所有权契约显式、向后兼容、变更需新 API版本号 POLICY OrtCApiOwnershipPolicy() def plan_ownership(requested: Ownership, policy: OrtCApiOwnershipPolicy POLICY) - Ownership: return policy.resolve(requested)所有 C API 张量接口都读POLICY默认 COPY、变更走新 API、头文件写明、版本号递增外部调用方不再被静默坑。七、解决方案第三层断言 / CI 守护把“所有权显式、向后兼容、变更需新 API”做成断言。下面用 pytest 守护import pytest def test_default_is_copy(policy): assert policy.default_ownership is policy.default_ownership.COPY assert policy.resolve(None) is policy.default_ownership.COPY def test_no_silent_change(policy): assert policy.forbid_silent_semantics_change is True assert (change AddInitializerToGraph to take ownership silently in policy.forbidden_patterns) def test_header_documented(policy): assert policy.document_ownership_in_header is True def test_version_bump_on_change(policy): assert policy.require_api_version_bump is True def test_take_requires_explicit_api(policy): # 接管必须通过显式 API 表达而非改默认行为 assert policy.resolve(policy.default_ownership.TAKE) is \ policy.default_ownership.TAKE这五组断言锁住(1) 默认 COPY(2) 禁止静默改语义(3) 头文件写契约(4) 变更需版本号(5) 接管需显式 API。CI 跑通即代表 C API 所有权契约不会再悄悄坑外部调用方。八、排查清单遇到 Chromium WebNN 在AddInitializerToGraph后崩溃看崩溃类型double free / use-after-free → 所有权契约错位本题。确认时序合 #28123 之后才崩 → 该 PR 改了所有权。查 C API 契约头文件是否写明传入Ort::Value是拷贝还是接管。改显式契约恢复 COPY 默认提供...TakeOwnership显式接管 API。版本化 文档所有权变更递增ORT_API_VERSION头注释写明。统一到OrtCApiOwnershipPolicyCI 断言禁止静默改语义。端到端Chromium WebNN 建图/释放不再崩溃ASan 干净。九、小结AddInitializerToGraph ownership-semantics change in #28123 breaks C API callers (Chromium WebNN crash)的根因是PR #28123 把AddInitializerToGraph的所有权语义从“拷贝/调用方持有”改成了“移动/函数接管”但没有在稳定的 C API 契约上同步——Chromium WebNN 作为外部 C API 调用方仍按旧契约在传完权重后释放那块Ort::Value于是图与调用方重复释放double free或误用已移交内存use-after-free只在外部调用方暴露崩溃。最小修复是在 C API 层明确所有权默认保持 COPY向后兼容接管语义通过显式命名的...TakeOwnershipAPI 提供并在头文件注释与ORT_API_VERSION上同步结构性改进是用唯一的OrtCApiOwnershipPolicy固化契约CI 用五组断言守护“显式、向后兼容、变更需新 API版本号”。记住C API 是对外稳定契约内部 PR 可以优化但绝不能静默改变“谁拥有内存”这件事。

相关新闻

2026/8/15 5:54:21

OpenClaw+Remotion+TTS+Whisper:零成本AI自动化短视频制作全流程拆解

1. 从零到九千:一个视频创作者的“低成本奇迹”前几天,我随手发的一个视频,播放量从平时的几十、几百,一下子冲到了九千多。最让我意外的是,这个视频的制作成本,算下来可能连一毛钱都不到。我不是什么剪辑大…

2026/8/15 5:54:21

AI智能体记忆系统架构:从向量检索到多Agent协同实战

1. 项目概述:从“金鱼脑”到“过目不忘”的智能体进化在AI智能体(Agent)的开发与应用浪潮中,一个核心的瓶颈问题日益凸显:记忆。早期的智能体,甚至包括一些当前看似复杂的系统,常常表现得像个“…

2026/8/15 5:54:21

AI绘图Prompt工程实战:高效生成专业架构图的核心技巧

1. 项目概述:当架构师遇上AI画笔最近和几个技术团队负责人聊天,发现一个挺有意思的现象:大家画架构图的工具越来越“卷”了。从早年的Visio、PPT,到后来的Draw.io、Lucidchart,再到现在的Mermaid、PlantUML这类代码绘图…

2026/8/15 6:49:24

Pathfinder API二次开发与人群仿真实践指南

1. Pathfinder API接口与二次开发概述Pathfinder作为专业的人群仿真软件,其API接口开放为开发者提供了强大的扩展能力。通过API,我们可以实现仿真流程自动化、定制化分析报告生成、与其他系统集成等高级功能。这套接口基于标准的REST架构设计&#xff0c…

2026/8/15 6:49:24

Linux文件操作核心命令:mv、rm、cp详解与实战避坑指南

1. 项目概述:为什么文件操作是Linux的基石如果你刚开始接触Linux,可能会觉得满屏的命令行让人望而生畏。但相信我,一旦你掌握了文件移动、删除和复制这几个核心操作,整个系统在你眼中就会变得清晰起来。这不仅仅是学会几个命令那么…

2026/8/15 6:49:24

Windows IIS搭建FTP/HTTP文件服务器:从SMB共享到服务化分享

1. 从“共享文件夹”到“服务化分享”的转变在Windows环境下,文件分享最常见的方式莫过于右键文件夹,选择“授予访问权限”来设置SMB共享。这个方法简单直接,局域网内的其他Windows电脑通过\\计算机名\共享名就能访问。但它的局限性也很明显&…

2026/8/15 6:49:23

Windows 10自建文件共享服务:FTP与HTTP服务器搭建全攻略

1. 项目概述:为什么要在Windows 10上自建文件分享服务?在团队协作或者跨设备传输文件时,你是不是也遇到过这样的场景:用微信传大文件有大小限制,速度还不稳定;用网盘吧,上传下载要等半天&#x…

2026/8/15 6:49:23

智元机器人技术解析:从AI大脑到关节小脑的具身智能实践

这次我们来看一个关于机器人创业的深度分析。标题“王兴兴的三年机器人创业语录,从‘不做人形’到610亿”背后,是智元机器人创始人王兴兴在短短三年内,带领公司从零到估值610亿的惊人历程。这不仅是资本市场的故事,更是技术路线选…

2026/8/15 6:44:23

Claude Code 从安装到实战:AI 编程助手如何提升企业级开发效率

你是不是也遇到过这样的场景:面对一个复杂的项目需求,明明知道大概方向,但具体实现时却卡在某个技术细节上,或者写出的代码总是有各种小问题需要反复调试?又或者,团队来了新人,你需要花大量时间…

2026/8/14 4:27:24

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/14 4:27:24

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/15 0:04:00

AI 电动婴儿车智能功率 辅助控制、电源管理的完整选型方案

2026年随着 AI 技术在电动孕婴童用品中的深度渗透(如智能避障、自适应速度控制、能量回收),电动婴儿车对功率器件提出更高要求:高效率、小型化、低功耗、高可靠性。微碧半导体(VBsemi)基于 Trench 及 SGT 工…

2026/8/15 0:04:00

论文AIGC检测不达标完整教程!低门槛用5款工具逐步复检!

论文提交前自己先查一遍AI率,是2026年毕业生的常规动作。学校要求论文AI率低于30%,乃至于20%才能答辩… 很多同学发现一个尴尬的事情:同一篇论文,知网查出来AI率35%,维普查可能是48%,大雅、朱雀又是另外的数…

2026/8/14 4:27:24

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/15 4:56:16

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/14 4:27:24

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…