Windows зависает из-за чрезмерного выделения памяти 64-битным процессом

Когда я запускаю 64-битную программу в Windows (версия 7 и выше), и программа пытается выделить слишком много памяти (около 100% физической памяти), система останавливается. Если я не уловлю это вовремя и не убью нарушающий процесс, система перестанет отвечать на запросы и потребуется полная перезагрузка. Очевидно, что программе не следует пытаться выделять столько памяти, но могут возникать ошибки, и я хочу защитить другие запущенные процессы от влияния любых таких ошибок в коде, над которым я работаю, при тестировании / отладке. (Это было меньшей проблемой в 32-разрядных системах, поскольку ограничение логической памяти обеспечивало защиту от общесистемного дросселя памяти.)

Итак, у меня есть два вопроса:

  • Может ли процесс ограничить потребление памяти? Существует ли системный вызов в Windows, который может установить ограничение памяти, так что выделение за пределами этого предела приведет к сбою вместо сбоя всей системы?

  • В качестве альтернативы, есть ли способ установить ограничение памяти для каждого процесса в масштабе системы или установить ограничение для конкретного приложения?

Вот пример кода, который заставляет мой компьютер зависать. Он был скомпилирован с Visual Studio 10.0 в конфигурации x86_amd64, и я запустил его на ноутбуке с 16 ГБ оперативной памяти под Windows 8.1. Он пытается выделить 32 ГБ памяти. Беги на свой страх и риск.

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

3

Решение

Вероятно, лучший вариант для процесса, чтобы поставить себя в Работа в Windows и применить ProcessMemoryLimit вариант. (Один улов: это не сработает, если процесс уже находится в задании, например, потому что он запускается как сценарий запуска или запланированная задача.) Вы также можете использовать ту же технику, чтобы ограничить использование памяти другим процессом, который вы запускаете (или это уже работает).

Кроме того, вы можете попробовать раскрутить поток, который использует CreateResourceMemoryNotification обнаружение низкого уровня физической памяти и прекращение процесса. Но вы можете обнаружить, что это ложные срабатывания. (Это, конечно, не следует оставлять в рабочем коде.)

4

Другие решения

Основываясь на полезном ответе Гарри Джонстона, я собрал немного кода, который можно добавить в начале программы, чтобы наложить ограничение на выделение памяти этой программой как фактор размера физической памяти.

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());
3

По вопросам рекламы [email protected]