Windows平台下C语言如何获取线程内存使用量?
线程内存监控与限制问题解决方案
错误码6(ERROR_INVALID_HANDLE)的根因与修复
错误码6对应ERROR_INVALID_HANDLE,你的GetProcessMemoryInfo调用失败,大概率是因为传入了线程句柄而非进程句柄——该函数要求第一个参数是进程句柄,而非线程句柄。此外,调用前必须正确初始化PROCESS_MEMORY_COUNTERS_EX结构体的cbSize字段,否则也会导致函数失效。
正确调用示例:
#include <windows.h> #include <psapi.h> BOOL GetCurrentProcessMemoryUsage(SIZE_T* pPrivateBytes) { PROCESS_MEMORY_COUNTERS_EX pmc; pmc.cbSize = sizeof(PROCESS_MEMORY_COUNTERS_EX); // 必须初始化结构体大小 if (!GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) { DWORD err = GetLastError(); // 可打印err排查,err=6即为句柄无效 return FALSE; } *pPrivateBytes = pmc.PrivateUsage; // 获取进程私有内存使用量 return TRUE; }
内存限制错误思路纠正
CreateThread的第二个参数dwStackSize仅控制线程栈的初始预留/提交大小,并非线程的总内存上限。操作系统会根据需要自动扩容栈(除非指定STACK_SIZE_PARAM_IS_A_RESERVATION),且该参数不限制堆、全局变量等其他内存区域,因此用它限制内存完全无效。
正确的内存限制方案
1. 进程级内存限制(作业对象)
如果要限制整个进程的内存使用,使用**作业对象(Job Object)**是标准方案:
HANDLE CreateMemoryLimitedJob(SIZE_T maxMemoryBytes) { HANDLE hJob = CreateJobObject(NULL, NULL); if (hJob == NULL) return NULL; JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0}; jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; jeli.ProcessMemoryLimit = maxMemoryBytes; if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli))) { CloseHandle(hJob); return NULL; } // 将当前进程加入作业 if (!AssignProcessToJobObject(hJob, GetCurrentProcess())) { CloseHandle(hJob); return NULL; } return hJob; }
注意:进程加入作业后无法退出;作业对象仅能限制进程级内存,无法单独限制单个线程。
2. 线程级内存跟踪(自定义分配钩子)
要单独监控/限制某个线程的内存使用,需要Hook该线程的内存分配函数(如malloc、VirtualAlloc),统计分配与释放的内存量:
- 用
SetWindowsHookEx设置线程钩子,拦截内存分配调用。 - 维护线程本地存储(TLS),记录该线程的内存总使用量。
- 每次分配/释放时更新统计值,超过阈值时触发错误。
主线程前后内存差值误差大的原因
进程内存是全局共享的,其他线程、系统服务、DLL加载/卸载等操作都会影响内存统计,因此“主线程执行前后差值”的方法误差必然很大,不建议使用。改用实时循环调用GetProcessMemoryInfo(循环中加入Sleep(10)避免CPU占用过高)的方式更可靠。
内容的提问来源于stack exchange,提问作者user23548623
相关产品推荐
相关产品推荐

