Page 236 - 《软件学报》2026年第3期
P. 236

李清伟 等: Go  语言程序的内存性能与安全问题实证研究                                                   1199


                    RQ1: Go  语言程序的内存访问特征是什么? 这些访问特征如何影响内存问题的识别和优化?
                    在现代语言和编译器的设计中, 为了平衡编译速度和程序性能, 分析和优化算法通常聚焦于最常见的场景, 这
                 要求对程序特征有整体的理解. 本研究旨在探索现实世界中                    Go  语言程序在其独特内存管理与访问机制下的内存
                 访问特征, 识别影响性能的内存使用模式, 并据此为               Go  语言编译器或分析工具的改进提供指导.
                    RQ2: Go  语言程序存在哪些内存安全问题, 这些问题在开源项目中的分布情况和常见代码模式如何?
                    为了减少内存安全问题的影响, 并帮助开发者和静态分析工具研制者更有效地识别和解决这些问题, 本研究
                 分析  Go  程序中常见内存安全问题 (如内存泄漏、空指针解引用) 的分布与表现, 探索其主流的问题代码模式, 同
                 时评估这些问题在开源项目中的修复方式、所需成本和规模, 以提供改进方向和优化建议.
                    RQ3: Go  语言程序中的内存安全问题模式如何归纳与检测?
                    通过归纳和总结内存问题模式, 如果能够针对一些相对简单的模式实现自动检测, 则有助于减少类似问题在
                 社区中的重复出现. 虽然       Go  语言生态中已有一些代码检查工具, 这些工具在提升软件质量和可靠性方面发挥了
                 重要作用, 但它们可能未覆盖某些特定的内存安全问题模式. 本研究以                      RQ1  和  RQ2  的方向为基础, 进一步探索如
                 何利用静态代码模式实现内存问题的高效检测和定位. 此外, 还设计并实现了一种用于检测内存泄漏问题中特定
                 模式 (L2-3) 的自动检测工具.
                    本文的主要贡献如下.
                    (1) 设计一个开源项目分析框架         PatStat, 它不仅能分析和统计     Go  项目中各类基本访存操作的分布, 还支持对
                 不限于   Go  语言的开源项目, 通过关键词搜索         Issues 和  pull requests (PRs), 进行问题及其修复的统计分析, 并进一
                 步辅助人工深入分析.
                    (2) 用  PatStat 框架分析  996  个  1  年内有更新的  Go  语言开源项目, 得到如下结果.
                    (a) 在各类基本内存访问操作中, 域访问和解引用操作的占比分别为                    25.44%  和  17.63%, 仅次于直接变量访问
                 操作 (占比   51.10%), 在分析和优化时可重点关注. 进一步的研究表明, 对于如               p.f.a 这类连续域访问和解引用操作,
                 只需对单层操作如       p.f 进行精确建模即可达到较为理想的分析精度.
                    (b) 具体类型对象转换为接口的模式可能引发隐式堆分配. 在所有模式中, 赋值语句和调用语句占比最高, 分
                 别为  20.16%  和  77.48%, 合计  97.64%, 为主要模式. 进一步分析发现, 这两类模式中分别有         23.65%  和  37.24%  的实
                 例可能引起隐式堆分配, 有潜在的内存优化空间, 值得重点关注.
                    (3) 通过对内存相关的      GitHub Issues 的分析, 总结出如下非并发内存安全问题在          Go  语言中的表现及模式.
                    (a) 内存泄漏: 尽管   Go  引入了垃圾回收机制, 但在新兴应用中内存泄漏问题依然存在, 且模式多样. 例如, 某些
                 资源仍需手动释放, defer 延迟机制无法完全解决遗漏调用的问题 (L1-2                模式), slice 表达式处理不当也可能导致内
                 存泄漏 (L2-3 模式) 等.
                    (b) 空指针解引用: 空指针解引用问题在           Go  语言中仍频繁发生, 已识别出        5  类主要问题模式, 适合通过代码
                 检查工具进行进一步检测和预防.
                    (c) 悬垂指针: 虽然在    Go  的语言机制下几乎不会出现悬垂指针问题, 但当开发者自行设计引用机制时仍可能
                 引发此类问题. 此类问题的检查需要更高层次的抽象分析, 而不是局限于语句级或函数级的简单分析.
                    (4) 在  RQ2  的研究中, 发现并总结了     Go  代码中可能导致内存泄漏的         L2-3  模式, 并据此开发了代码检查工具.
                 通过基于   PatStat 对  996  个项目生成的  966  个项目数据库进行分析, 得到如下结果.
                    (a) 在  966  个项目中, 共报告了  574  处可能存在问题的代码位置.
                    (b) 对其中  70  个报告进行人工审查, 发现       6  个为正确报告, 64  个为误报. 将人工审查正确的报告形成了 5             个
                 Issues (其中  2  个问题合并为  1  个  Issue) 提交至  GitHub, 最终获得  1  个肯定的回复, 2  个认为是误报, 还有  2  个尚未
                 收到回复.
                    本文第   1  节介绍  Go  语言相关的背景知识以及研究动机. 第           2  节介绍所设计的    PatStat 分析框架. 第  3–5  节分
                 别介绍对   3  个  RQ  的研究与分析结果. 第   6  节讨论研究方法的有效范围与局限性. 第            7  节介绍相关工作.
   231   232   233   234   235   236   237   238   239   240   241