3

У меня следующая проблема: в программе есть ошибка, подобная следующей

int main() {
  for(;;) {
    char *p = (char*)std::malloc(1024);
    std::memset(p, 1, 1024);
  }
}

И он продолжает распределять память до тех пор, пока моя система не начнет выгружать страницы других приложений в пользу этой программы, и я больше не могу ничего делать на коробке. Я сталкивался с этой проблемой несколько раз в разных приложениях (сегодня это было с бета-версией Moonlight 2 в Firefox). Я думаю, что проблема в том, что из-за программы происходит обмен памяти другой программы, и поэтому она может использовать больше физической памяти.

Естественно я посмотрел в ulimit, и нашел две настройки

-m максимальный размер резидентного набора
-v размере виртуальной памяти

Я прочитал, что первый обозначает общий объем физической памяти, который процесс может использовать одновременно. Мне кажется, что это более разумно, чем общий размер виртуальной памяти, потому что она может использоваться совместно, и это может вообще не иметь никакого значения, потому что она все равно выгружается. Поэтому я добавил следующее в свой .bashrc посмотрев на обычные размеры резидентных наборов с top , который варьируется до 120 МБ для обычной сессии Firefox.

# limit usage to 256MB physical memory out of 1GB
ulimit -m 262144

Но после запуска моего вышеупомянутого тестового фрагмента, он все еще отключил мою систему, и мне пришлось ждать около 5 минут, пока терминал не распознал нажатия клавиш ^C Обычно, если я не реагирую в течение первых нескольких секунд, в этих ситуациях я могу только нажать кнопку сброса, что мне действительно не нравится - так у кого-нибудь есть стратегия, как это решить? Почему не работает физическое ограничение? Мне кажется, что таким образом у других приложений все еще должно быть достаточно физической памяти для разумной реакции.

3 ответа3

1

Вы пробовали с флагом -v ?

Резидентный рабочий набор определяется максимальным объемом памяти, сохраняемым в качестве рабочего набора в ОЗУ перед заменой. Таким образом, он не будет ограничивать общий объем памяти, включая замененные части рабочего набора. Флаг -v должен сделать работу.

ВИРТУАЛЬНЫЙ РАЗМЕР ПАМЯТИ: наиболее полезный из ограничений, связанных с памятью, поскольку он включает в себя все типы памяти, включая файлы стека, кучи и отображаемые в памяти файлы. Попытки выделить память сверх этого лимита потерпят неудачу с ошибкой нехватки памяти.

Удивительно, что ресурсы в сети, подробно описывающие это, не так легко найти! Я провел эксперимент на моей Linux-коробке.

Останавливается с исключением с

  ulimit -v 100000

и не с флагом -m . Единственное, что меня удивило, это исключение:

segmentation fault

Я бы ожидал out of memory .

1

Я думаю, что реализация ulimit отстой случайным образом практически на любой операционной системе. Я использую ulimit -S -v в Linux шесть лет. Шесть! И кажется, что некоторые ядра больше не поддерживают его. Я получил Mac и OS X 10.6 не поддерживает его. Я также пытался с -m. На моем старом рабочем столе с Ubuntu 9.04 ulimit -S -v работает нормально.

Действительно, я ищу реальное решение для этого. Я просто не могу поверить, что люди в Apple, например, позволяют своей программе сходить с ума по памяти.

0

Классическая утечка памяти. Боюсь, вам нужно исправить ошибку в рассматриваемом приложении, операционная система мало что может сделать. Все, что может сделать операционная система, - это ограничить память для одного приложения, но тогда соответствующее приложение будет аварийно завершать работу / зависать, и, возможно, использовать операционную систему или хотя бы xorg с ней.

Вы можете ld_preload другой версии malloc, и добавить поток, чтобы освободить его через указанное количество секунд. Я сомневаюсь, что это будет работать, хотя ...

Вам понадобится вот это:http://lattice.umiacs.umd.edu/files/functions_tr.pdf

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .