当前内存使用情况显示总是比任务管理器多大约14MB

时间:2017-03-23 20:20:14

标签: 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:

debugText

任务管理器:

Task Manager:

资源监控:

Resource Monitor

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

debugText:

debugText

任务管理器:

Task Manager

资源监控:

Resource Monitor

修改

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

1 个答案:

答案 0 :(得分:5)

任务管理器不使用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);

它显示的&#34;内存(私人工作集)&#34;列是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_EX的{​​{1}}基数非常接近VM_COUNTERS_EX2但不完全(没有PROCESS_MEMORY_COUNTERS_EX)成员)。 [Peak]VirtualSize在内部调用GetProcessMemoryInfo(),然后将ZwQueryInformationProcess(hProcess, ProcessVmCounters)复制到VM_COUNTERS_EX

在Windows 10的任务管理器中,&#34;内存(由各个进程保留的物理内存)&#34;列显示PROCESS_MEMORY_COUNTERS_EX(以1024字节为增量)。这个相同的值显示在&#34;详细信息&#34;标签(私人工作集)。由于未知原因,该值以1000字节为增量显示,因此实际值始终高出1.024倍。

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

如果要像任务管理器一样显示内存,请使用NT API中kernelbase.dll的{​​{1}}成员。如果你不能使用它,那么你将得到与任务管理器不同的结果。

如果您不喜欢NT API,或者不理解它,这不是我的问题(或者也许有人可以现在通过使用某些&#34;来获取PrivateWorkingSetSize。记录&#34; API?)。如果任务管理器使用NT API,这也不是我的选择。