Почему моя программа иногда выдает ошибку segfault при нехватке памяти, а не выбрасывает std :: bad_alloc?

У меня есть программа, которая реализует несколько алгоритмов эвристического поиска и несколько доменов, предназначенных для экспериментальной оценки различных алгоритмов. Программа написана на C ++, построена с использованием набора инструментов GNU и работает в 64-битной системе Ubuntu. Когда я запускаю свои эксперименты, я использую команду bash ulimit, чтобы ограничить объем виртуальной памяти, которую может использовать процесс, чтобы моя тестовая система не начала подкачку.

Определенные комбинации алгоритма / тестового экземпляра достигают установленного мной предела памяти. В большинстве случаев программа выдает исключение std :: bad_alloc, которое выводится обработчиком по умолчанию, после чего программа завершается. Иногда, вместо этого, программа просто перестает работать.

Почему моя программа иногда выдает ошибку segfault при нехватке памяти, а не сообщает о необработанном std :: bad_alloc и завершается?


person Brad Larsen    schedule 02.04.2010    source источник
comment
segfault может быть вызван не только тем, что вы достигли предела памяти   -  person Andrey    schedule 02.04.2010
comment
Я прекрасно осведомлен. В тех случаях, когда я видел segfault, процесс использовал объем памяти, близкий к указанному мной пределу. Я почти уверен, что наблюдаемые мной ошибки сегментации не связаны с ошибками в моем коде.   -  person Brad Larsen    schedule 02.04.2010
comment
Рассматривали ли вы простой запуск в GDB (ну некоторые из них), чтобы увидеть, в какой части кода возникают ошибки сегментации?   -  person Shiroko    schedule 02.04.2010


Ответы (3)


Одна из причин может заключаться в том, что по умолчанию Linux чрезмерно использует память. Запрос памяти у ядра, похоже, работает нормально, но позже, когда вы действительно начинаете использовать память, ядро ​​замечает «О, черт, у меня заканчивается память», вызывает убийцу нехватки памяти (OOM), который выбирает некоторые процесс жертвы и убивает его.

Описание этого поведения см. На странице http://lwn.net/Articles/104185/.

person janneb    schedule 02.04.2010
comment
Возможно. Еще немного информации, я работал как единственный пользователь в тестовой системе с 48 ГБ памяти. Я работал с ulimit виртуальной памяти 47 ГБ, что должно оставить много основной памяти для ОС. Ссылка на статью датируется 2004 годом. Актуальна ли она сегодня? - person Brad Larsen; 02.04.2010

Это может быть какой-то код, использующий no-throw new и не проверяющий возвращаемое значение.

Или какой-то код может улавливать исключение, но не обрабатывать его или повторно генерировать.

person Zan Lynx    schedule 02.04.2010

Что сказал яннеб. Фактически Linux по умолчанию никогда не выбрасывает std :: bad_alloc (или возвращает NULL из malloc ()).

person Nemanja Trifunovic    schedule 02.04.2010
comment
Я предполагаю, что вы имеете в виду, что std :: bad_alloc никогда не запускается по умолчанию в Linux. Почему же тогда я вижу, что std :: bad_alloc выбрасывается из программ C ++ в нескольких системах Linux, когда программа достигает своего предела памяти? - person Brad Larsen; 02.04.2010
comment
Кроме того, я думаю, вы имеете в виду malloc' rather than free '. На странице руководства Linux для malloc не звучит так, будто NULL никогда не будет возвращен. - person Brad Larsen; 02.04.2010
comment
Как я уже сказал, это поведение по умолчанию. Взгляните на эту ветку: stackoverflow.com/questions/1592535/ - person Nemanja Trifunovic; 02.04.2010
comment
Я подумал, что даже с чрезмерной фиксацией linux быстро выходит из строя, если вы запрашиваете больше, чем некоторая верхняя граница, которую он знает, что никогда не может удовлетворить, или если вы просите больше, чем осталось в пространстве виртуальной памяти (это довольно редкое явление на я бы подумал, что это 64-битная система) или больше, чем может быть непрерывно зарезервировано в адресном пространстве (опять же, это не произойдет случайно в 64-битной системе). Конечно, я мог ошибаться. - person Steve Jessop; 02.04.2010
comment
@Steve Это было некоторое время назад, но IIRC на моем рабочем столе x86_64 с 8 ГБ ОЗУ моя простая тестовая программа, которая выделяла память, но не касалась ее, смогла выделить около 90 ГБ, прежде чем malloc () вернул NULL. - person janneb; 02.04.2010
comment
Я не сказал, что это очень жесткая верхняя граница, которой он никогда не сможет удовлетворить :-). Предположение при чрезмерной фиксации заключается в том, что приложения, как правило, выделяют больше памяти, чем они фактически используют, либо из-за действительно потраченного впустую пространства (например, экспоненциального роста массива), либо просто из-за того, что максимальная отметка зарезервированного пространства отличается от максимальной отметки. фактического использования. Подумайте о копировании списка в массив, удалив при этом каждый узел списка. В любой момент вы используете только половину зарезервированной памяти. Я предполагаю, что 90 ГБ были той точкой, в которой ядро ​​решило, что это, вероятно, проблема. - person Steve Jessop; 02.04.2010
comment
@Steve: Поведение Linux зависит от настроек соотношения избыточной и избыточной фиксации. Некоторые дистрибутивы изменяют значение по умолчанию, чтобы отключить неограниченное превышение лимита, но устанавливают соотношение в 1,5 или 2 раза больше объема ОЗУ. - person Zan Lynx; 03.04.2010