审查Key Catcher源码发现进程结束调用EmptyWorkingSet,是否安全、有无替代方案?
接口基础功能说明
EmptyWorkingSet是psapi.dll导出的系统内存管理接口,核心作用是将指定进程当前常驻物理内存的工作集(进程当前加载在物理内存中的代码、数据页面集合)中可被回收的页面全部转移到系统页面文件,强制释放该进程占用的物理内存。
你看到的调用中传入的参数-1,是Windows约定的当前进程伪句柄,等价于调用GetCurrentProcess()获取的句柄,代表操作的目标是程序自身的内存空间。
当前调用方式的问题分析
结合代码在进程退出时执行的场景,这种调用本身不存在恶意窃取数据的逻辑,但属于完全无收益的冗余操作,也是网上“不要随意使用该接口”的警示的核心来源:
- 进程进入退出流程后,Windows系统的内核进程管理器会自动全额回收该进程占有的所有物理内存、虚拟内存资源,不需要手动调用任何接口做收尾,这时候调用
EmptyWorkingSet本质是多执行了一次完全无收益的冗余系统调用,不会带来任何内存占用优化效果。 - 如果在非退出场景随意调用该接口——很多开发者为了刷程序低内存占用的表面跑分,在程序启动、用户交互过程中强制清空工作集——反而会造成明显的性能损耗:被换出的内存页面如果后续被程序访问,会触发大量缺页中断,需要从磁盘重新把页面读回物理内存,白白增加磁盘IO开销,拖慢程序响应速度。
- 单从这行代码判断,不存在恶意键盘记录器的典型行为(比如全局钩子捕获按键、静默网络回传数据等),不需要因为这行代码直接判定程序存在风险。
接口的正确使用边界
该接口并不是完全不能用,只有在满足以下条件时调用才有实际价值:
- 调用时机必须是程序长时间进入闲置状态、确定短时间内不会响应用户操作的节点(比如音乐播放器切到后台播放、工具类程序最小化到托盘超过10分钟无交互),此时清空工作集释放的物理内存可以供前台正在运行的程序使用,缓解系统整体的物理内存压力。
- 绝对不要在进程启动加载、用户正在交互操作、进程退出收尾的阶段调用,这几个阶段调用要么会拖慢程序启动/响应速度,要么属于完全的冗余操作。
- 调用时需要确保传入的进程句柄有对应的内存操作权限,避免出现权限不足导致的调用失败。
更优的替代方案
绝大多数场景下都不需要手动调用EmptyWorkingSet来做内存优化,替代方案的收益和可靠性更高:
- 依靠Windows自带的内存调度机制就可以实现合理的内存分配:当系统物理内存不足时,内核会自动识别后台闲置进程的不常用页面,按照优先级换出到磁盘,这个过程不会打断前台程序的响应速度,效果远好于手动强制清空工作集。
- 程序退出阶段的资源清理,只需要正常释放自身申请的堆内存、关闭打开的句柄、注销注册的系统钩子即可,剩余的内存回收逻辑完全交给操作系统处理,不需要手动干预。
- 针对你调研到的这款Key Catcher程序,这行退出时调用
EmptyWorkingSet的代码可以完全删除,对程序功能、实际资源占用没有任何负面影响,还能减少一次无意义的系统调用开销。
内容的提问来源于stack exchange,提问作者mxyzptlk
相关产品推荐
相关产品推荐

