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

1202                                                       软件学报  2026  年第  37  卷第  3  期



                     4.66 GiB                                     6k
                                                                  5k
                     3.73 GiB                                     4k
                   内存使用量  2.79 GiB                               Clients数量  3k
                     1.86 GiB
                    954.00 MiB                                    2k
                                                                  1k
                                                                   0
                       0 B   15:40  15:50  16:00  16:10  16:20  16:30  15:40  15:50  16:00  16:10  16:20  16:30
                                         时刻                                        时刻
                                   Resident memory  Resident memory             Connected XDS clients
                                    (a) Memory usage                          (b) Number of clients
                        图 1 grpc/grpc-go/issues/4758  内存泄漏问题, 在用户数量下降之后, 内存使用量仍然保持不变

                 代码  3. grpc-go Issue#4758: slice 操作前未置空导致内存泄漏.

                 1.   var item *itemType
                 2. − item, q.queue = q.queue[0], q.queue[1:] // q.queue[0] will not be used forever
                 3. + item = q.queue[0]
                 4. + q.queue[0] = nil
                 5. + q.queue = q.queue[1:]
                 6.    ... // destroy item

                  1.4   面向  Go  语言程序的内存安全问题检测工具
                    为了缓解内存安全问题, 除了           Go  语言采用的运行时崩溃等机制, 一些代码检查工具也被开发和使用.
                 Staticcheck [12] 是一个较为先进的  Go  语言代码检查工具, 能够检测标准库的误用、并发问题、冗余代码和内存性
                 能等问题. 针对内存安全问题, Staticcheck      包括了对冗余     nil 检查  [26–29] 、可能发生空指针解引用的检测      [30] 等分析
                 规则. golangci-lint  [14] 集成了多个代码检查工具, 支持代码风格检查, 未使用函数和变量的检查等. go vet 工具             [13]  作
                 为  Go  语言内置的检查工具, 可以检测       defer 使用时的常见错误、不必要的比较函数指针和               nil 模式等.
                    尽管这些检测工具在发现和修复常见的编程错误方面发挥了重要作用, 但它们仍然存在一定的局限性. 因此,
                 对  Go  语言内存安全问题进行实证分析显得尤为重要. 通过对                Go  代码中的内存安全问题进行深入研究, 可以帮助
                 开发者设计和构建更有效的代码检查工具, 从而更早发现潜在的内存安全隐患.
                  2   方法设计

                    为了深入探讨      Go  语言的内存性能和安全问题及其关联模式, 本文设计了如后文图                   2  所示的分析框架     PatStat.
                 针对  RQ1, 基于  CodeQL [31] 设计了统计分析工具   QLStat, 能对不同基本访存操作进行全面统计分析. 针对              RQ2, 设
                 计了  IssueAnalyzer 工具, 能通过关键词检索    GitHub  的  Issues/PRs, 结合统计与人工分析, 总结  Go  语言中内存安全
                 问题的分布特征及常见代码模式. 针对            RQ3, 为  RQ2  中识别的典型内存问题模式编写查询语句, 利用             QLStat 工具
                 对选择的    Go  代码仓库 (repository, Repo) 进行扫描查询, 以发现潜在的内存安全问题, 并探索可能的自动检测
                 方法.
                    本文通过    GitHub  的  REST API 获取了最近  1  年内有更新的   Go  语言代码仓库. 选择最近       1  年内更新的仓库,
                 旨在确保其处于积极维护状态, 能够反映             Go  语言生态的活跃部分及当前发展趋势和实际应用情况. 最终, 共收集
                 到  996  个仓库, 并且基于这些仓库开展后续的模式统计分析.
                  2.1   RQ1: 访存操作的模式统计
                    为了回答    RQ1, 设计了如图    3  所示的  QLStat, 基于抽象语法树 (AST) 识别    Go  语言项目中不同基本访存操作
                 并统计分布情况, 为编译器优化提供指导. QLStat 基于             CodeQL  对代码仓库进行模式匹配, 合并各仓库的分析结
                 果, 从而实现不同基本访存操作的统计分析. CodeQL             是一款代码扫描工具, 能够提取程序的多种信息, 如抽象语
   234   235   236   237   238   239   240   241   242   243   244