不能。GetProcessHandleCount 已废弃且不可靠,Windows 8+ 始终返回0;应使用 NtQueryInformationProcess + ProcessHandleCount 获取当前进程有效句柄数。

GetProcessHandleCount 能否直接拿到当前进程的句柄总数?
不能。GetProcessHandleCount 是 Windows API 中一个**已被废弃且实际不可靠**的函数:它在 Windows 8+ 上始终返回 0,文档明确标注为 “This function is not supported”;即便在旧系统上,它也只返回内核估算值,不反映真实引用计数(例如未关闭的 std::shared_ptr 持有的 HANDLE 不计入,而重复 DuplicateHandle 的副本会计入)。别用它。
真正可用的方案:NtQueryInformationProcess + ProcessHandleCount
Windows 内核提供稳定的 NtQueryInformationProcess,通过 ProcessHandleCount 类型可获取当前进程句柄表中**已分配且有效**的句柄数量(即 CloseHandle 后立即减少的数值)。这是监控泄漏最接近真实的指标。
实操要点:
- 需手动加载
ntdll.dll并解析NtQueryInformationProcess函数指针(微软未导出该函数) - 结构体
PROCESS_BASIC_INFORMATION不需要;直接传入nullptr缓冲区 +sizeof(DWORD),让系统返回所需大小 - 返回值是
NTSTATUS,成功时为0(不是TRUE),错误码如0xC0000005表示访问违规(通常因缓冲区太小或权限不足) - 必须以
PROCESS_QUERY_INFORMATION权限打开当前进程(GetCurrentProcess()已满足)
// 示例:获取当前进程句柄数
HANDLE hProc = GetCurrentProcess();
DWORD handleCount = 0;
NTSTATUS status = NtQueryInformationProcess(
hProc,
ProcessHandleCount,
&handleCount,
sizeof(DWORD),
nullptr
);
if (status == 0) {
printf("Current handle count: %u
", handleCount);
}
想查整个系统的句柄总数?没有直接 API,只能绕行
Windows 不提供全局句柄总数接口。常见误操作是遍历所有进程调用 NtQueryInformationProcess(ProcessHandleCount) 累加——但这样得到的是“各进程句柄表长度之和”,**不等于系统总引用数**,因为:
立即学习“C++免费学习笔记(深入)”;
- 同一内核对象(如文件、事件)可能被多个进程以不同句柄号引用,每个进程都计入自己的
ProcessHandleCount - 系统进程(如
csrss.exe、wininit.exe)默认拒绝PROCESS_QUERY_INFORMATION权限,除非以 SYSTEM 权限运行 - 句柄表本身占用内存,但不参与用户态计数逻辑
真正能反映系统资源压力的是性能计数器:Process(*)Handle Count(PerfMon 中可见),其底层由内核维护,精度高且含权限隔离。若需程序化读取,应使用 PdhAddCounter + PdhCollectQueryData 访问 "\Process(_Total)\Handle Count"。
监控句柄泄漏时最容易忽略的三个点
句柄监控不是“取个数就完事”,关键在对比与上下文:
- 不要只看绝对值:
CreateFile失败报ERROR_TOO_MANY_OPEN_FILES时,句柄数可能才 2048 —— 因为默认进程句柄表上限是 16K,但每个线程栈会预占部分槽位,实际可用远低于理论值 - 注意句柄生命周期:C++ RAII 封装(如
unique_handle)能防泄漏,但若对象被std::move后又重复CloseHandle,会导致INVALID_HANDLE_VALUE错误,此时句柄数不变但逻辑已错 - GUI 程序额外消耗:每创建一个窗口、菜单、画刷都会新增 GDI 句柄,它们独立于内核句柄计数,需用
GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS)单独查
系统句柄统计本身无统一“总数”概念,进程级用 NtQueryInformationProcess(ProcessHandleCount),全局压力看 PerfMon 计数器,GDI/USER 资源另查——混用或漏查,监控就失去意义。


















