当前位置: 首页 > news >正文

CppCon 2018 学习:Better C++ using Machine Learning on Large Projects

尝试预防 Bug 的常见手段 & 机器学习在实际项目(如《彩虹六号:围攻》)中的应用

目标:减少生产环境中的 Bug

常见 Bug 预防手段(软件工程实践)

手段说明
代码评审 (Code Reviews)多人协作审查,避免明显逻辑错误
单元测试 / 功能测试快速验证每个模块是否符合预期
静态分析工具例如 Clang-Tidy、Coverity,发现内存泄露、未定义行为等
测试团队 (Testers)手工探索或系统测试各种场景
Beta 测试 / 测试服务器部署在真实用户中观察 bug 表现和系统行为
这些手段已经广泛用于大型游戏项目中,但仍不能完全避免 bug

Ubisoft 的进阶做法:机器学习预测 Bug 风险

由 Mathieu 与 Nicolas 共同介绍的两个部分:

Part 1:Mathieu – 如何利用 ML 预测 Bug 提交

主要流程:
  1. 回顾历史提交记录
    • 标记哪些 commit 曾引入 bug
  2. 提取提交的特征
    • 如代码变更的行数、修改的文件数、是否是新手开发者等
  3. 构建机器学习模型
    • 输入是 commit 的特征
    • 输出是该提交引入 bug 的概率(即“风险”)

Part 2:Nicolas – 应用于《彩虹六号:围攻》

成果与应用:
项目说明
Bug 引入率(Bug introduction rate)实际数据驱动衡量代码质量
风险预测辅助代码审查高风险提交会提醒更仔细审查
VS Code / Git 工具集成开发时即可看到风险警告

结论:为何重要?

  • 越早发现 bug,修复成本越低
  • 静态分析 + 测试 ≠ 万无一失,ML 还能提前提醒风险
  • 特别适合超大型代码库(如 AAA 游戏项目)

你也可以这样做(即使没有 ML)

  • 用 Git 历史分析 bug 热点模块
  • 使用 Clang-Tidy/Cppcheck 配合 CI 自动运行
  • 将 PR 风险评分(如改动文件数、作者经验)作为评审参考
  • 对提交增加“自动标记标签”(例如高风险、需要多审)
    如果你需要,我可以:
  • 帮你写一个 git 提交分析脚本
  • 设计一个简单的“风险打分系统”示例
  • 整合 clang-tidy + Git Hooks + CI 模板

几个版本的冒泡排序算法代码片段,我对它们统一整理,并 添加了详细注释 和解释,以便理解其含义与结构。

第一部分:错误的原始冒泡排序实现

void bubbleSort(int arr[], int n) {int i, j;for (i = 0; i < n - 1; i++)               // 外层控制趟数,总共进行 n-1 趟for (j = 0; j < 1 - j; j++)           //  这个条件写错了,1 - j 会变成负值或 0,循环根本无法执行if (arr[j] > arr[j + 1])swap(&arr[j], &arr[j + 1]);   // 交换两个元素
}

问题

  • for (j = 0; j < 1 - j; j++) 是错误的条件,应该是 j < n - i - 1

第二部分:带优化的冒泡排序(布尔标志 swapped)

while (swapped) {swapped = false;         // 标志是否发生过交换j++;                     // 当前趟数,逐渐减少比较长度for (int i = 0; i < n - j; i++) {if (arr[i] > arr[i + 1]) {swap(&arr[i], &arr[i + 1]);  // 交换相邻元素swapped = true;             // 有交换,说明还没排好}}
}

说明

  • 这是典型的优化型冒泡排序,加了 swapped 标志避免无意义比较。
  • 当一整趟下来没有发生交换时,表示已经排好序,可以提前结束循环。

第三部分:变量重命名版本(混淆式)

while (V1) {V1 = false;V2++;  // 趟数for (int V3 = 0; V3 < V4 - V2; V3++) {if (V5[V3] > V5[V3 + 1]) {M1(&V5[V3], &V5[V3 + 1]);  // 调用交换函数V1 = true;}}
}

对应命名含义(推测):

  • V1:布尔标志 swapped
  • V2:当前趟数 j
  • V3:内层索引 i
  • V4:数组长度 n
  • V5:待排序数组 arr
  • M1:交换函数 swap

第四部分:完整的冒泡排序封装函数 M1 + M2

void M1(int V1[], int V2) {int V3, V4;for (V3 = 0; V3 < V2 - 1; V3++) {for (V4 = 0; V4 < V2 - V3 - 1; V4++) {if (V1[V4] > V1[V4 + 1]) {M2(&V1[V4], &V1[V4 + 1]);  // 调用 M2 函数进行交换}}}
}

含义

  • 这是标准的冒泡排序实现。
  • M2 是一个交换函数(类似标准库 swap),但未给出定义。

推荐交换函数实现 M2:

void M2(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}

总结对比

版本特点是否可运行
第一段错误版本不可运行,循环条件错误
第二段优化版本推荐,含 swapped
第三段混淆命名正确,但难读
第四段封装函数正确实现冒泡排序

1. 机器学习用于代码缺陷预测的背景和流程

  • 历史数据(Historical Data IN)
    收集大量历史代码提交数据,提取相关的特征(比如文件年龄、目录数、代码行数、复杂度、提交者数、测试覆盖率等)。
  • 新数据(New Data)
    对当前的代码提交也同样提取这些特征。
  • 模型(Model)和预测(Prediction)
    使用机器学习模型(线性回归、分类模型等)来预测新的提交是否可能引入缺陷。

2. 特征工程(Machine Learning Features)

这些特征涵盖了:

  • 文件相关:文件年龄、文件数、目录数、子系统
  • 贡献者相关:提交者数量、活跃度(Dev R-XP, Dev S-XP)
  • 代码复杂度:复杂度、熵、唯一改动、注释密度、日志密度
  • 其他指标:代码稳定性、Fan In / Fan Out(调用关系)、测试覆盖率

3. 数学基础

  • 特征矩阵(Feature Matrix)
    x = [ f A 1 f B 1 … f M 1 ⋮ ⋮ ⋱ ⋮ f A N f B N … f M N ] x = \begin{bmatrix} f_{A1} & f_{B1} & \dots & f_{M1} \\ \vdots & \vdots & \ddots & \vdots \\ f_{AN} & f_{BN} & \dots & f_{MN} \end{bmatrix} x= fA1fANfB1fBNfM1fMN
  • 协方差矩阵(Covariance Matrix)
    通过计算特征之间的协方差,理解特征之间的相关性。
  • 线性回归模型示例
    预测函数形如:
    预测 = Subsystems × x + Directories × y + Files × z + ⋯ + Age × 0.20 + UniqueChange × 0.30 + Sexp × 0.50 + … \text{预测} = \text{Subsystems} \times x + \text{Directories} \times y + \text{Files} \times z + \dots + \text{Age} \times 0.20 + \text{UniqueChange} \times 0.30 + \text{Sexp} \times 0.50 + \dots 预测=Subsystems×x+Directories×y+Files×z++Age×0.20+UniqueChange×0.30+Sexp×0.50+
    其中不同特征带有不同权重,反映它们对缺陷引入的影响力。

4. 机器学习模型性能

  • 预测代码提交是否引入缺陷
    • 精确率(Precision)约为 70.05%
    • 召回率(Recall)约为 71.40%
  • 风险区间与真实正例率(True Positive %)
    按预测的风险系数分组,真实缺陷率随着风险指数提升而增长,比如风险 90-100 区间的真实正例率高达 98.99%。

5. 实践中的潜力与改进方向

  • 代码中的常见问题:
    • 函数中出现大量 bug
    • 代码复杂度过高,可能有性能问题
    • 缺少 .Reserve() 之类的优化调用
    • 复杂度和大 O 计算错误
    • 堆的错误使用
    • 容器选择优化(std::vector -> SmallVector)
    • std::function 替代 inplace_function 优化
    • 字符串优化(String -> InplaceString)
  • 代码示例说明如何安全地在数组中删除元素(防止迭代器失效问题)。
http://www.lqws.cn/news/594073.html

相关文章:

  • [Python 基础课程]字符串
  • Tomcat9部署jsp产生错误FileCountLimitExceededException
  • 网络安全监测探针功能
  • Python 数据分析:DataFrame,生成,用字典创建 DataFrame ,键值对数量不一样怎么办?
  • python+uniapp基于微信小程序的PS社区系统
  • 基于3D卷积神经网络与多模态信息融合的医学影像肿瘤分类与可视化分析
  • JVM调优实战 Day 15:云原生环境下的JVM配置
  • Go 服务如何“主动”通知用户?SSE广播与断线重连实战
  • 【算法】动态规划:python实现 1
  • 前端开发git的使用(常用命令和规范)
  • Python ORM 完全指南:从基础到高级实践
  • UI前端大数据可视化实战技巧分享:如何选择合适的颜色与图表类型?
  • MATLAB构建capm和三因子模型
  • t检验​、​z检验、χ²检验中的P值
  • rabbitmq动态创建交换机、队列、动态绑定,销毁
  • 企业上网行为管理:零信任安全产品的对比分析
  • go语言安装达梦数据完整教程
  • 大数据在UI前端的应用创新研究:基于自然语言处理的用户意图识别
  • Spring生态的核心组件演进
  • 21、鸿蒙学习——使用App Linking实现应用间跳转
  • 推客系统小程序终极指南:从0到1构建自动裂变增长引擎,实现业绩10倍增长!
  • 使用tensorflow的线性回归的例子(二)
  • 【第二章:机器学习与神经网络概述】04.回归算法理论与实践 -(2)支持向量回归(SVR)
  • linux魔术字定位踩内存总结
  • GORM 删除的重要特性:软删除实践案例(优化版)
  • 前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
  • React:利用React.memo和useCallback缓存弹窗组件
  • Oracle 常用函数
  • 设置linux静态IP
  • 测试第六讲-测试模型分类