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

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



                 代码  12. N2: 某些操作的执行取决于指针是否为          nil 问题模式.

                 1.   // N2-1: cockroachdb/cockroach/pull/59477
                 2.   + defer func() {
                 3.   +   if err != nil {
                 4.   +     // If an error occurs, set the serializer to nil to avoid any future attempts to call other methods
                 5.   +     d.serializer = nil // fixed here
                 6.   +   }
                 7.   + }()
                 8.     if err := d.serializer.Finish(); err != nil {
                 9.       return err
                 10.   }
                    结论  5. 空指针解引用问题在       Go  语言中仍然存在. 尽管     Go  语言在运行时添加了空指针解引用的检查操作以
                 确保程序安全, 但是在开源社区中仍然存在大量因指针未检查空值而导致程序崩溃的                            Issues. 针对这类问题, 建议
                 在代码审查中使用静态分析工具, 如           nilaway [60] 和  nilness [61] , 检查是否存在空指针解引用的问题.
                  4.3.3    悬垂指针问题模式
                    本文人工分析了       50  条通过搜索“dangling pointer”关键词和采样得到的       Issues. 在这些  Issues 中, 只有  2  条
                 Issues [62,63] 与悬垂指针直接相关, 并且它们是由于      CGO (Go  语言调用  C  语言的机制) 和   unsafe 机制导致的. 其余
                 的  Issues 仅在内容和评论中提及了      dangling  关键词. 大多数情况下, 包含这些      Issues 的应用引入了自定义的引用
                 系统, 如  kubernetes 实现了集群资源的引用系统, 并实现了更高层次的垃圾回收                 [64] , 用于清理集群资源; 版本控制
                 工具  git-lfs 和  pachyderm  实现了文件对象的引用系统, 通过在文件系统中存储           objects 来表示版本信息. 在这些引
                 用系统中, 悬垂对象通常是引用系统中更高抽象层次的对象, 例如集群资源对象、commit 对象等, 需要程序员手
                 动维护引用关系的有效性.
                    结论  6. 悬垂指针问题在     Go  语言中并不常见, Go    语言较好地解决了悬垂指针问题.

                  4.4   内存安全问题的修复
                    为了了解内存安全问题的修复难度与修复成本, 本文进一步统计了包含有效                          PR  的  Issues 的修复时间、修复
                 规模. 统计方法详见第      2.2  节.
                    ● 修复时间间隔. 本文对所有人工分析的内存安全问题模式进行了修复时间的统计, 其修复时间间隔的统计
                 直方图如图    5  所示.
                    在内存泄漏问题中, 大部分问题在           30  天之内被修复, 但也有     8  个问题需要至少     60  天才能解决. 相比之下, 无
                 效地址或空指针解引用问题大多在             10  天之内修复, 只有一个问题需要        50–60  天的时间才能解决. 整体而言, 无效
                 地址或空指针解引用问题的修复时间较短. 另外, 有               2  个  Issues [65,66] 的修复时间为负数, 即  2  个  PR  在  Issue 被创建
                 的  5  天前已提交修复. 经过人工审查发现, 有评论提到在出现时间更早的                  PR  修复后的代码版本中, Issue 所提及的
                 问题已无法复现, 可能已被修复. 因此, 无效地址或空指针解引用问题通常能够较快得到解决.
                    ● 修复代码规模. 本文对所有人工分析的内存安全                Issues/PRs 进行了修复代码规模的统计. 修复代码变更行
                 数箱型图如图     6  所示. 其中内存泄漏问题的修复代码变更中位数为 60              行, 无效地址或空指针解引用问题的修复代
                 码变更中位数为      48  行. 但是从  75%  分位数来看, 内存泄漏问题的修复代码变更规模为              111  行, 比空指针解引用问
                 题的修复规模     251  行要小.
                    结论  7. 内存泄漏问题通常在       30  天内被修复, 但是也有个别问题修复时间超过             60  天. 无效地址或空指针解引
                 用问题通常在     10  天内修复, 修复速度较快, 甚至出现因版本未及时更新而导致重复提出                    Issue 的情况. 从修复规模
                 来说, 两类问题的修复变更代码行数中位数均为数十行, 修复规模相对较小.
   248   249   250   251   252   253   254   255   256   257   258