当我在Windows(版本7及更高版本)上运行64位程序并且程序试图分配太多内存(接近100%的物理内存)时,系统会停止运行。如果我没有及时赶上它并杀死违规过程,系统将无法响应并需要重新启动。显然,程序不应该尝试分配如此多的内存,但是可能会发生错误,并且我希望保护其他正在运行的进程免受测试/调试时代码中任何此类错误的影响。 (这在32位中不是问题,因为逻辑存储器限制为系统范围的存储器阻塞提供了安全网。)
所以我有两个问题:
进程是否可以限制其内存消耗?在Windows中是否存在可以设置内存限制的系统调用,以便超出限制的分配将失败而不是使整个系统崩溃?
或者,有没有办法设置系统范围的每进程内存限制或为特定应用程序设置限制?
这是一个导致计算机冻结的示例代码。它是在x86_amd64配置中使用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;
}
答案 0 :(得分:4)
可能最好的选择是将流程置于Windows job并应用ProcessMemoryLimit选项。 (一个问题:如果进程已经在一个作业中,这将不起作用,例如,因为它作为启动脚本或计划任务运行。)您还可以使用相同的技术来限制另一个进程的内存使用你启动(或已经运行)。
或者,您可以尝试启动使用CreateResourceMemoryNotification的线程来检测低物理内存条件并终止该过程。但你可能会发现这是误报。 (这当然不应该留在生产代码中。)
答案 1 :(得分:3)
根据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());