aardio 文档

统计口径与兼容边界

地址空间不是物理内存

本库基于 VirtualQueryEx 的区域状态进行枚举。MEM_COMMIT 表示区域的提交状态,不能解释成当前驻留 RAM;未触碰的已提交页面可以尚未分配对应物理页。

private.virtualBytes 包括私有的已提交区和仅保留区。映像、内存映射文件的虚拟大小也不等于进程独占 RAM。映像/映射区发生写时复制后,VirtualQueryEx 仍可能报告原来的 MEM_IMAGE / MEM_MAPPED 类型。

进程计数器由 process.usage 获取并独立显示;PrivateUsage 与按区域累加的私有已提交量可能不同,不强行对账成同一指标。

分配、保护页与线程栈

AllocationBase 聚合对应底层分配范围,不是逐个 malloc/new 对象。一个堆段可以服务大量语言对象。

PAGE_GUARD 是通用保护机制,普通私有分配也能具有保护页。没有保护页的区域也不一定不是栈。因此本库使用 guardedPrivateAllocations,不提供伪精确的 stackCount,更不会宣称找到了栈泄漏。

Protect 在 MEM_RESERVE 下未定义,MEM_FREE 的 allocation/type/protect 等字段也未定义;库不依赖这些值。

非原子扫描与自观测

不暂停目标,不安装 Hook,不读取目标内存内容。各个区域、名称、线程数、计数器可能在不同时刻取得。

32 位目标与 LAA

首版只处理 x86 目标,地址值使用精确的 32 位无符号数。64 位或其他架构目标明确拒绝;并不是“先扫描低 4 GiB 再当成全进程”。

不能把所有 x86 目标都硬编码为 2 GiB,也不能只看采集器自己的最高地址。库先查询目标已加载映像的 Large Address Aware 标志,再探测其应用查询上界。非 LAA 目标限制在其约 2 GiB 应用范围;LAA 目标在系统支持时覆盖高地址。

尤其不要把非 LAA 进程高地址处由系统保留的巨大范围误当作应用泄漏。系统保留范围在其他位置也可能存在;榜单不擅自断言每项都是业务分配。

Native API 依赖

为避免读取目标内存的 PE 头,也避免磁盘文件与已加载映像不一致,库使用:

该接口不属于稳定的公开 Win32 合约。查询失败、返回长度或目标机器类型不符时明确失败,不读取未初始化数据,也不猜测 LAA。 当前实现已在 Windows 11 x64、32 位 aardio 下验证普通与 LAA 子进程;其他 Windows 版本及 x86 Windows 的特殊地址配置没有本机实测保证。

这些是只读的进程映像元信息查询,不等于读取目标进程的内存内容。句柄权限为 PROCESS_QUERY_INFORMATION | SYNCHRONIZE;不申请 ALL_ACCESS、VM_READ、VM_WRITE 或 VM_OPERATION,不自动提权。

快照对比不是事件追踪

快照仅记录两个时刻的状态。期间同地址被释放再复用且属性相同,可能完全不可见;不能据此推断对象身份相同。

因此 diff 核对进程 PID、创建 FILETIME、架构和范围,按区间对齐计算状态/保护/分配基址变化,拒绝不完整快照,但不声称能发现所有分配事件或自动证明泄漏。

参考实现依据

发布快照给他人前请注意 imagePath、mappedPath 可能包含本机用户名、程序安装位置等路径信息。

Markdown 格式