罕见的 AMD 集显驱动内存泄漏

发布时间:

信息

从 24.7.1 版本 AMD 驱动开始,本文提到的内存泄漏问题得到了解决,请放心更新。

如果你的 Windows 系统最近出现了长期使用后越来越卡, 在任务管理器中检查,发现显示的内存使用量巨高,但显示的进程占用内存并没有这么多的情况。 恭喜你,你遇到了老生常谈的内存泄漏(Memory Leak)问题,但有的时候它很特殊。 绝大部分 Windows 系统的普通用户是没有能力去追踪内存泄漏以及解决问题的,瞎试验的话很难猜到是驱动程序的问题。 由于中文互联网上还没有相关的资料,我打算写一篇文章来记录一下,以供后来者参考。

TL;DR:

  • 如果你用的是 AMD 集显,请将驱动 回退 到 23.10.2 等稳定的 23 大版本。
    • 用旧版本的 AMD Software: Adrenalin Edition 覆盖安装不起作用
    • 执行干净卸载需要 DDUAMD Cleanup Utility for Windows®
    • 顺便提一下,如果出现驱动程序超时,也可以通过回退到 23 大版本解决。
  • 如果你有独立显卡,禁用集显也可以解决此问题(🐫 骆驼玩法,并不推荐)。
  • 还有治标不治本的办法:使用类似 Windows Memory Cleaner 这样的工具

这个问题是在 24 的某个版本引入的, 最近 AMD 发布了 24.6.1 版本, 大半年了,官方还没修这个问题,太离谱了。每次发版,下面都有一堆用户定期跟进吐槽...

参考机器配置

  • 机器:铭凡 UM773, 服役有一年半有余(迷你主机爱好者容易碰到此问题)
  • CPU:AMD Ryzen 7 7735HS + AMD Radeon™ 680M 核显(集成显卡, iGPU)
  • 驱动:24.5.1(AMD 到现在都没有解决这个问题)
  • 内存:英睿达 32GB DDR5 4800MHz x2(在小主机算比较大的了,之前都没注意到)
  • 独显:RTX 3060Ti 独立显卡(eGPU, 蜂鸟 2 显卡坞接入,实际上不影响此问题)

简单思路概述

在 Windows 中,如果一个进程退出,但是它的句柄没有被正确关闭(释放),那么这个进程就会变成僵尸进程。 FindZombieHandles 可以帮助发现僵尸进程,但这种方法并不总是有用。 更一般地,我们可以通过用 Sysinternals Suite 的 RAMMap 工具查看实际的物理内存占用情况, 在我的 AMD 集显内存泄漏的例子中,可以发现存在大量无法回收的 Page Table 内存碎片, 且来自 cmd.execonhost.exe, 这是不正常的。 如果出现无法借助任务管理器直观定位的内存泄漏,通常是由于内核模式应用(如驱动程序)导致的。

接下来就是用合适的工具如 PoolMon 来监控内核内存池的使用情况, 寻找非分页池(NPaged, 不能被分页到磁盘上的内存区域,它们始终驻留在物理内存中) 分配(Allocs)远大于释放(Frees)的标签,发现罪魁祸首 Proc, EtwSMiP2.

对比 PoolMonX 中的 pooltag.txt, 只有 MiP2 是未知的, Google 一下关键词就能找到其他人的类似问题记录。 由于一些人在更新驱动后第一时间就碰到了这个问题,所以可以快速确定是 AMD 驱动程序的问题。 而我的内存容量较大,所以后面发现的时候很难直接定位。

当然,如果网络上没有相关的参考信息,后面就需要按照 标准处理流程 自己分析了:

想象一下,如果是个不用 Google 的 AMD 核显玩家,碰到类似这种问题会有多无语。

导致内存泄漏的具体原因

目前官方还没有给出明确的解释,但是可以确定的是这个问题是由于 AMD 集显驱动程序引起的。 可能是后台的一些计划任务干的?具体细节和原因,我也不敢保证, 毕竟没有用 WDK 去做内核调试和验证,就不胡乱猜测了。主要目的是解决问题,不是找原因。 至于这些 “有娘生,没娘养” 的僵尸进程的父亲是谁,我也不知道,也不想知道。

AMD 最新的有关内存泄漏的安全报告是 CVE-2023-4969, 但这更多是数据泄漏的问题。

AMD NOT YES! 说好了要一起战未来呢? 驱动能用的话,看来还是不要轻易更新啊!

参考资料、工具与文档