c++ - 当前内存使用显示总是比任务管理器多 ~14MB

标签 c++ windows winapi memory taskmanager

我目前正在使用 this answer 中的代码,按照评论中的建议进行了一些细微的修改。但是,无论我在内存中分配多少对象,列出的内存使用量总是比任务管理器列出的多 ~14MB。为什么会这样?

std::stringstream ss;

PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;

ss << "\nMEM: " << (physMemUsedByMe / 1024 / 1024) << " MB";    

debugText.setString(ss.str());

正常构建的结果:

调试文本:

debugText

任务管理器:

Task Manager:

资源监视器:

Resource Monitor

分配 10,000 个虚拟对象时的结果:

调试文本:

debugText

任务管理器:

Task Manager

资源监视器:

Resource Monitor

编辑:

按照评论建议使用资源监视器 (perfmon) 后,我发现 Working Set 列与我正在使用的内存列表功能相匹配。但是,我仍然对为什么 Working Set 列和 Private 列之间存在 ~14MB 的差异感到困惑(后者是任务管理器似乎使用的).为什么会这样?

最佳答案

任务管理器不使用 Win32 API GetProcessMemoryInfo() 函数。它使用 NT API ZwQueryInformationProcess() 函数,将 ProcessInformationClass 参数设置为 ProcessVmCounters

从 Windows 10 开始,定义了以下结构(在 ntddk.h 中):

typedef struct _VM_COUNTERS_EX2 {
    VM_COUNTERS_EX CountersEx;
    SIZE_T PrivateWorkingSetSize;
    ULONGLONG SharedCommitUsage;
} VM_COUNTERS_EX2, *PVM_COUNTERS_EX2;

任务管理器使用 VM_COUNTERS_EX2 类似于下面的代码:

VM_COUNTERS_EX2 vm;
ZwQueryInformationProcess(hProcess, ProcessVmCounters, &vm, sizeof(vm), 0);

它为“内存(专用工作集)”列显示的值是 vm.PrivateWorkingSetSize 字段。

看起来此时不存在与此类似的 Win32 API。如何查看:

typedef struct _VM_COUNTERS_EX {
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;// note this !!
    ULONG PageFaultCount;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    SIZE_T QuotaPeakPagedPoolUsage;
    SIZE_T QuotaPagedPoolUsage;
    SIZE_T QuotaPeakNonPagedPoolUsage;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivateUsage;
} VM_COUNTERS_EX;

VM_COUNTERS_EX2VM_COUNTERS_EX 基数非常接近 PROCESS_MEMORY_COUNTERS_EX 但不精确(没有 [Peak]VirtualSize) 成员)。 GetProcessMemoryInfo() 在内部调用 ZwQueryInformationProcess(hProcess, ProcessVmCounters),然后将 VM_COUNTERS_EX 复制到 PROCESS_MEMORY_COUNTERS_EX


在 Windows 10 的任务管理器中,“内存(由各个进程保留的物理内存)”列显示 PrivateWorkingSet(以 1024 字节为增量)。这个相同的值显示在“详细信息”选项卡(私有(private)工作集)下。由于未知原因,该值以 1000 字节为增量显示,因此实际值始终高出 1.024 倍。

但您使用“总”工作集 - WorkingSetSize - 它是“私有(private)”和“共享”工作集的总和(您需要在“详细信息”选项卡中添加列才能查看此,默认情况下仅显示私有(private)内存)。因此,结果始终存在差异 (14 MB) - 这是“共享”工作集(通常是常见的 DLL,如 ntdll.dllkerner32.dll , kernelbase.dll 等)。当您分配内存(10,000 个虚拟对象)时,这种差异不会改变。 “私有(private)”工作集增长,但“共享”工作集保持不变(因为没有加载/卸载新的 DLL)。

如果您想像任务管理器那样显示内存,请使用 NT API 中 VM_COUNTERS_EX2PrivateWorkingSetSize 成员。如果您不能使用它,那么您将得到与任务管理器不同的结果。

如果您不喜欢 NT API,或者不理解它,这不是我的问题(或者也许有人可以现在通过使用一些“记录在案的“API?”。如果任务管理器使用 NT API,这也不是我的选择。

关于c++ - 当前内存使用显示总是比任务管理器多 ~14MB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42986220/

相关文章:

winapi - WINAPI中透明按钮的正确做法

c++ - Windows下"Standard I/O only"权限

c++ - 指针如何知道所指向元素的结尾?

c# - 以编程方式设置控制台窗口大小和位置

c - 如何在 Windows 上设置 pthreads?

java - Apache Thrift Python-Java 'Connection Refused'

c++ - 如何更改 AfxMessageBox 中的语言?

c++ - 如何制作具有自定义移位值的模板

c++ - 在 Win32 中确定按键和按键的最快方法是什么?

c++ - Boost 编译在 boost/move/unique_ptr.hpp 中失败