当我在Windows(版本7及以上)上运行64位程序并且程序尝试分配太多内存(接近100%的物理内存)时,系统停止运行。 如果我没有及时赶上并杀死违规程序,系统将无响应,需要重新启动。 显然,程序不应该尝试分配这么多的内存,但是可能会发生错误,我想保护其他正在运行的进程免受testing/debugging时正在处理的代码中的任何此类错误的影响。 (这在32位中不是什么问题,因为逻辑内存限制提供了系统内存扼stream圈的安全networking。)
所以我有两个问题:
一个进程是否可以限制内存消耗? 在Windows中是否有系统调用可以设置内存限制,这样超出限制的分配将会失败,而不是整个系统崩溃?
另外,是否有任何方法来设置系统范围的每进程内存限制或为特定的应用程序设置限制?
这里是一个示例代码,导致我的电脑冻结。 它是用x86_amd64configuration的Visual Studio 10.0编译的,我在Windows 8.1下用16 GB RAM的笔记本上运行它。 它试图分配32 GB的内存。 运行风险自负。
int main(void) { const static int csNumArrays=10, csArraySize=800000000; int i, j, **p; p=new int*[csNumArrays]; for (i=0; i<csNumArrays; ++i) { p[i]=new int[csArraySize]; for (j=0; j<csArraySize; ++j) p[i][j]=j; } return 0; }
可能最好的选择是将进程置于Windows作业并应用ProcessMemoryLimit选项。 (一个问题:如果进程已经在某个工作中,那么这将不起作用,例如,因为它正在作为启动脚本或计划任务运行。)还可以使用相同的技术来限制另一个进程的内存使用情况你启动(或已经运行)。
或者,您可以尝试启动使用CreateResourceMemoryNotification的线程来检测低物理内存状况并终止进程。 但是你可能会发现这是误报。 (这当然不应该留在生产代码中。)
根据Harry Johnston的有用答案,我把一些可以在程序开始时添加的代码加入到程序的内存分配中,作为物理内存大小的一个因素。
ULONGLONG aMemSize; HANDLE aJob=::CreateJobObject(NULL, NULL); JOBOBJECT_EXTENDED_LIMIT_INFORMATION aLimit; // Get physical memory and set process memory limit to 75% of physical memory GetPhysicallyInstalledSystemMemory(&aMemSize); aMemSize*=size_t(768); // convert kb to bytes and apply 75% factor memset(&aLimit, 0, sizeof(aLimit)); aLimit.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_PROCESS_MEMORY; aLimit.ProcessMemoryLimit=aLimit.PeakProcessMemoryUsed=aLimit.JobMemoryLimit= aLimit.PeakJobMemoryUsed=aMemSize; ::SetInformationJobObject(aJob, JobObjectExtendedLimitInformation, &aLimit, sizeof(aLimit)); ::AssignProcessToJobObject(aJob, ::GetCurrentProcess());