返回「计算机、信息技术与工程」
Windows C++ 获取进程内存使用情况
本文目录 4 个章节
Windows C++ 获取进程内存使用情况
创建时间:2020/5/14 22:18
Windows 可通过 PSAPI 的 GetProcessMemoryInfo 读取进程内存计数器。常用字段包括:
WorkingSetSize:当前驻留在物理内存中的工作集;其中可能包含共享页面。PeakWorkingSetSize:进程生命周期内的工作集峰值。PrivateUsage:PROCESS_MEMORY_COUNTERS_EX提供的私有提交量,更接近该进程独自承担的已提交内存,但仍不等同于所有分析工具中的 “private working set”。PageFaultCount:累计缺页次数,不能单独代表性能问题。
不同工具的“内存占用”可能采用工作集、私有工作集、提交量或 PSS 等不同口径,比较前必须确认定义。
查询当前进程
#include <windows.h>
#include <psapi.h>
#include <cstddef>
#include <iostream>
#pragma comment(lib, "psapi.lib")
int main() {
PROCESS_MEMORY_COUNTERS_EX counters{};
counters.cb = sizeof(counters);
const BOOL ok = GetProcessMemoryInfo(
GetCurrentProcess(),
reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&counters),
sizeof(counters));
if (!ok) {
std::cerr << "GetProcessMemoryInfo failed, error="
<< GetLastError() << '\n';
return 1;
}
constexpr std::size_t MiB = 1024 * 1024;
std::cout << "Working set: "
<< counters.WorkingSetSize / MiB << " MiB\n";
std::cout << "Peak working set: "
<< counters.PeakWorkingSetSize / MiB << " MiB\n";
std::cout << "Private commit: "
<< counters.PrivateUsage / MiB << " MiB\n";
}
查询指定 PID
打开其他进程时只申请查询所需的最小权限,并检查句柄与 API 返回值:
#include <windows.h>
#include <psapi.h>
#include <iostream>
#pragma comment(lib, "psapi.lib")
bool PrintProcessMemory(DWORD processId) {
HANDLE process = OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ,
FALSE,
processId);
if (process == nullptr) {
std::cerr << "OpenProcess failed, error=" << GetLastError() << '\n';
return false;
}
PROCESS_MEMORY_COUNTERS_EX counters{};
counters.cb = sizeof(counters);
const BOOL ok = GetProcessMemoryInfo(
process,
reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&counters),
sizeof(counters));
if (ok) {
std::cout << "PID " << processId
<< ", working set=" << counters.WorkingSetSize
<< " bytes, private commit=" << counters.PrivateUsage
<< " bytes\n";
} else {
std::cerr << "GetProcessMemoryInfo failed, error="
<< GetLastError() << '\n';
}
CloseHandle(process);
return ok == TRUE;
}
某些受保护进程无法读取,提升到 SeDebugPrivilege 也不是通用解决方案。工具应正常处理访问被拒绝,并避免默认以管理员身份运行。
分析建议
- 固定构建、场景和采样时间,重复采样而非只看单点。
- 同时记录工作集、私有提交量和系统整体内存压力。
- 排查泄漏时结合堆快照、分配调用栈和对象生命周期。
- 64 位大小使用
SIZE_T/std::size_t,避免用%d截断。 - 句柄必须关闭;动态数组应使用标准容器或 RAII,避免手工
new[]/delete[]错配。