简体   繁体   English

由于64位进程的内存分配过多,Windows冻结

[英]Windows freezes due to excessive memory allocation of 64-bit process

When I run a 64-bit program on Windows (version 7 and up) and the program tries to allocate too much memory (close to 100% of physical memory) the system grinds to a halt. 当我在Windows(版本7及更高版本)上运行64位程序并且程序试图分配太多内存(接近100%的物理内存)时,系统会停止运行。 If I don't catch it in time and kill the offending process the system will become unresponsive and a hard reboot is required. 如果我没有及时赶上它并杀死有问题的过程,系统将无法响应并需要重新启动。 Obviously the program shouldn't try to allocate so much memory, but bugs can happen and I want to protect the other running processes from the effects of any such bugs in the code I'm working on when testing/debugging. 显然,程序不应该尝试分配如此多的内存,但是可能会发生错误,并且我希望保护其他正在运行的进程免受我在测试/调试时正在处理的代码中的任何此类错误的影响。 (This was less of a problem in 32-bits because the logical memory limit provided a safety net from system-wide memory choke.) (这在32位中不是问题,因为逻辑内存限制为系统范围的内存扼流圈提供了安全网。)

So I have two questions: 所以我有两个问题:

  • Can a process limit its memory consumption? 一个进程可以限制其内存消耗吗? Is there a system call in Windows that can set a memory limit, so that allocations beyond the limit will fail instead of crash the whole system? 在Windows中是否存在可以设置内存限制的系统调用,以便超出限制的分配将失败而不是使整个系统崩溃?

  • Alternatively, is there any way to set a system-wide per-process memory limit or to set a limit for a particular application? 或者,有没有办法设置系统范围的每进程内存限制或为特定应用程序设置限制?

Here's a sample code that causes my computer to freeze. 这是导致我的计算机冻结的示例代码。 It was compiled with Visual Studio 10.0 in x86_amd64 configuration and I ran it on a laptop with 16 GB RAM under Windows 8.1. 它是在x86_amd64配置中使用Visual Studio 10.0编译的,我在Windows 8.1下使用16 GB RAM的笔记本电脑上运行它。 It attempts to allocate 32 GB of memory. 它试图分配32 GB的内存。 Run at your own risk. 运行风险自负。

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;
}

Probably the best option is for the process to put itself into a Windows job and apply the ProcessMemoryLimit option. 可能最好的选择是让进程将自己置于Windows作业并应用ProcessMemoryLimit选项。 (One catch: this won't work if the process is already in a job, eg, because it is being run as a startup script or scheduled task.) You can also use the same technique to limit the memory usage of another process that you launch (or that is already running). (一个问题:如果进程已经在一个作业中,这将不起作用,例如,因为它作为启动脚本或计划任务运行。)您还可以使用相同的技术来限制另一个进程的内存使用你启动(或已经运行)。

Alternatively, you could try spinning up a thread that uses CreateResourceMemoryNotification to detect a low physical memory condition and terminate the process. 或者,您可以尝试启动使用CreateResourceMemoryNotification的线程来检测低物理内存条件并终止进程。 But you may find this is subject to false positives. 但你可能会发现这是误报。 (This should certainly not be left in production code.) (这当然不应该留在生产代码中。)

Based on Harry Johnston's helpful answer I put together a bit of code that can be added at the beginning of a program to impose a limit on that program's memory allocation as a factor of the physical memory size. 根据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());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM