Windows10下C++程序如何限制自身物理内存占用?
在Windows 10下用C++限制进程内存的正确方法
你的问题出在没有启用Job Object的内存限制标志——Windows只会在你明确告诉它要启用某个限制时,才会生效对应的参数。你的代码里只设置了MaximumWorkingSetSize,但没在LimitFlags里标记要启用这个限制,所以系统直接忽略了这个值。
我来给你修正代码,并解释关键要点:
关键问题分析
- 未设置LimitFlags:
JOBOBJECT_EXTENDED_LIMIT_INFORMATION中的BasicLimitInformation.LimitFlags必须包含对应的限制标志(比如JOB_OBJECT_LIMIT_WORKINGSET),否则系统不会应用你设置的MaximumWorkingSetSize。 - WorkingSetSize的单位是页面:每个页面默认是4KB,所以你设置的
1其实是4KB,但建议设置合理的测试值(比如1MB=256个页面),避免进程直接崩溃。 - 进程归属检查:确保当前进程没有被其他Job对象包含,否则
AssignProcessToJobObject会失败。
修正后的代码示例
#include <windows.h> #include <stdexcept> #include <iostream> void LimitProcessMemory() { // 创建Job对象 HANDLE hJob = CreateJobObject(nullptr, L"MyMemoryLimitJob"); if (hJob == nullptr) { throw std::runtime_error("Failed to create job object: " + std::to_string(GetLastError())); } // 检查当前进程是否已经在某个Job中 BOOL isInJob = FALSE; if (!IsProcessInJob(GetCurrentProcess(), nullptr, &isInJob)) { CloseHandle(hJob); throw std::runtime_error("Failed to check process job membership: " + std::to_string(GetLastError())); } if (isInJob) { CloseHandle(hJob); throw std::runtime_error("Process is already in a job, cannot assign to new job"); } // 将当前进程分配到Job中 if (!AssignProcessToJobObject(hJob, GetCurrentProcess())) { CloseHandle(hJob); throw std::runtime_error("Failed to assign process to job: " + std::to_string(GetLastError())); } // 配置内存限制 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobLimits = {0}; // 启用工作集(物理内存)限制 jobLimits.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_WORKINGSET; // 设置最小/最大工作集大小(单位:页面,1页面=4KB) // 这里设置最大为1MB(256*4KB),最小为64KB(16*4KB) jobLimits.BasicLimitInformation.MinimumWorkingSetSize = 16; jobLimits.BasicLimitInformation.MaximumWorkingSetSize = 256; // 可选:如果要限制虚拟内存总量(更严格的内存限制) // jobLimits.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_VM_SIZE; // jobLimits.VirtualMemoryLimit = 1024 * 1024 * 1024; // 1GB虚拟内存限制 // 应用限制 if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobLimits, sizeof(jobLimits))) { CloseHandle(hJob); throw std::runtime_error("Failed to set job limits: " + std::to_string(GetLastError())); } std::cout << "Memory limit applied successfully" << std::endl; } int main() { try { LimitProcessMemory(); // 这里写你的业务代码,测试内存占用 // 比如尝试分配大量内存,会触发系统限制 char* bigBuffer = new char[2 * 1024 * 1024]; // 尝试分配2MB,超过1MB工作集限制 delete[] bigBuffer; } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; }
额外说明
- 工作集限制 vs 虚拟内存限制:
JOB_OBJECT_LIMIT_WORKINGSET限制的是进程能使用的物理内存大小,系统会主动将超出部分的内存页交换到磁盘。JOB_OBJECT_LIMIT_VM_SIZE限制的是进程能分配的虚拟内存总量,一旦超过,内存分配操作(new/malloc)会失败(返回NULL或抛出std::bad_alloc),这种限制更严格。
- 权限问题:确保程序以足够的权限运行(普通用户权限通常足够,但如果进程是受保护的进程可能会失败)。
- Job对象的生命周期:Job对象会在所有关联进程退出后自动关闭,也可以手动调用
CloseHandle关闭。
内容的提问来源于stack exchange,提问作者Dominique
相关产品推荐
相关产品推荐

