Page 258 - 《软件学报》2026年第3期
P. 258
李清伟 等: Go 语言程序的内存性能与安全问题实证研究 1221
语言程序的数据竞争、死锁问题. 另外, 由于 Go 语言是类型安全的语言, 而 unsafe package 会破坏类型安全机制,
已有实证研究探索了 unsafe package 在真实世界中使用情况以及潜在危害 [41,84] . 但是对除并发安全、类型安全之
外, 针对 Go 语言中其他内存问题的研究工作相对较少. 例如, 对于内存泄漏问题来说, 在 Go 语言相关的研究工作
中 Saioc 等人 [85] 通过检测部分死锁的 Go 协程 Goroutine 来检测内存泄漏问题. CodeQL 分析的已有工作 [86,87] 主要
聚焦于漏洞检测. 本工作的创新之处在于, 利用 CodeQL 这种将程序代码解析存储到数据库中, 然后使用查询语言
进行查询得到代码查询结果的范式, 实现对现实世界 Go 项目中内存相关基本操作分布情况的统计分析. 同时, 基
于这一方法, 本工作对大量真实世界 Go 项目进行了 L2-3 模式的检查, 给出可能存在内存泄漏问题的报告.
● 基于静态代码模式的优化. 特定的静态代码模式可能造成性能问题. 对这些模式 (包括静态分析所建模的语
句) 的统计分析有助于指导静态分析和程序优化的方向, 从而缓解性能问题. 例如, He 等人 [88] 基于 3 类普遍存在的
容器使用模式, 识别可能影响分析精度的依赖上下文的对象, 在分析时只为这些对象添加上下文, 而不为其他对象
添加, 从而在接近相同的精度下显著提升指针分析速度. 本文对连续域访问次数和连续解引用的次数也表明: 在分
析这两类模式时, 仅对单次操作进行比较准确的建模即可获得较大的收益, 对于多次操作可以采取保守的建模方式
以获得较快的分析速度. Selakovic 等人 [10] 的工作对 JavaScript 中导致性能问题的常见静态代码模式进行了总结, 指
导应用开发者避免常见的错误, 指导研究者开发相应的性能工具, 指导 JavaScript 引擎开发者处理这些流行的性能
瓶颈模式. 本文在第 3 节针对 Go 语言中的基本访存操作进行了建模, 发现域访问操作和解引用操作在所有基本访
存操作中合计占约 42%, 是潜在的性能优化点, 需要在程序建模时重点关注. 进一步分析表明, 在所有转换为接口的
模式中, 赋值语句和调用语句中包含接口转换的模式最多, 约占 98%. 同时, 在这些转换接口的模式中, 被转换类型
为非指针类型的模式占 34.96%. 这些模式可能存在隐式堆内存分配, 内存分配优化可以重点关注这些模式.
8 总 结
本文提出了一套针对 GitHub 中开源 Go 仓库的实证分析框架, 并利用该框架对 GitHub 中筛选出来的 996 个
Go 语言仓库中的内存访问模式、内存安全问题以及修复模式进行了实证分析与总结.
首先, 针对 Go 语言的内存访问模式, 本文使用 QLStat 对仓库进行了自动统计与分析, 分析结果显示解引用和
域访问操作分别占 17.63% 和 25.44% 的比例. 这一结果说明, 在进行编译器优化和静态分析工具建模时, 必须重
点关注这两类操作. 进一步分析发现, 大多数的域访问和解引用操作均为单次访问. 与此同时, 针对 Go 独有的
interface 类型, 分析结果表明, 在转换为接口的模式中, assign 模式和 call 模式占据了绝大多数, 在分析接口相关的
内存分配时需要着重考虑.
其次, 本文通过人工分析 130 个 Issues/PRs, 并留下 44 条确定为内存问题的 Issues/PRs. 这些 Issues 的类别分
为内存泄漏、无效地址或空指针访问、悬垂指针这 3 类. 进一步的模式分析显示, 内存安全问题在开源 Go 语言
项目中频繁出现, 并且最常见的类型是无效地址或空指针访问问题, 而开发工具、云/微服务、容器/虚拟机等领域
的项目更容易发生内存安全问题. 此外, 针对每一类的内存安全问题, 本文也进行了模式的细分.
最后, 针对模式细分中的 L2-3 问题模式 (即由切片表达式赋值 s3 = s2[start:] 导致内存泄漏的问题模式), 本文
使用 QLStat 框架开发了代码检查工具, 分析了 966 个项目数据库, 报告了 574 处问题. 在这些问题中, 人工审查了
70 个问题, 最终发现 6 个可能正确的报告, 并通过 GitHub Issues 提交给相关仓库, 最终有 1 个被开发者确认为可
能存在内存泄漏.
References
[1] Go. Case studies. 2025. https://go.dev/solutions/case-studies
[2] Go. Proposal: arena: New package providing memory arenas. 2025. https://github.com/golang/go/issues/51317
[3] Wang C, Zhang MR, Jiang Y, Zhang HF, Xing ZC, Gu M. Escape from escape analysis of Golang. In: Proc. of the 42nd ACM/IEEE Int’l
Conf. on Software Engineering: Software Engineering in Practice. Seoul: ACM, 2020. 142–151. [doi: 10.1145/3377813.3381368]
[4] Ding BY, Li QW, Zhang Y, Tang FG, Chen JB. MEA2: A lightweight field-sensitive escape analysis with points-to calculation for
Golang. Proc. of the ACM on Programming Languages, 2024, 8: 1362–1389. [doi: 10.1145/3689759]

