Есть ли смысл ловить segfault?

Я знаю, что при наличии достаточного контекста можно надеяться на конструктивное использование (т. е. восстановление) из условия segfault.

Но стоит ли усилий? Если да, то в какой ситуации?


person jldupont    schedule 23.12.2009    source источник


Ответы (6)


Вы не можете действительно надеяться оправиться от segfault. Вы можете определить, что это произошло, и, если возможно, выгрузить соответствующее состояние конкретного приложения, но вы не можете продолжить процесс. Это потому, что (среди прочего)

  • Поток, в котором произошел сбой, не может быть продолжен, поэтому у вас есть единственные варианты: longjmp или завершение потока. Ни один из них не является безопасным в большинстве случаев.
  • В любом случае, вы можете оставить мьютекс/блокировку в заблокированном состоянии, что заставит другие потоки ждать вечно.
  • Даже если этого не произойдет, вы можете утечь ресурсы
  • Даже если вы не сделаете ни одну из этих вещей, поток, в котором произошла ошибка сегментации, мог оставить внутреннее состояние приложения несогласованным после сбоя. Несогласованное внутреннее состояние может привести к ошибкам данных или дальнейшему плохому поведению впоследствии, что вызовет больше проблем, чем просто выход.

Так что в целом нет смысла перехватывать его и делать что-либо, КРОМЕ того, чтобы завершить процесс довольно резко. Нет смысла пытаться записать (важные) данные обратно на диск или продолжать выполнять другую полезную работу. Есть определенный смысл выгружать состояние в журналы, что делают многие приложения, а затем завершать работу.

Возможно, полезным может быть выполнение exec() вашего собственного процесса или наличие сторожевого процесса, который перезапускает его в случае сбоя. (NB: exec не всегда имеет четко определенное поведение, если ваш процесс имеет> 1 поток)

person MarkR    schedule 23.12.2009
comment
Хорошее резюме, но я не согласен по причине, которую я упомянул в своем ответе; бывают случаи, когда вы делаете что-то конкретное, что может вызвать segfault, и восстановление не является проблемой. - person Chris Arguin; 24.12.2009

Ряд причин:

  1. Чтобы предоставить дополнительную информацию о приложении для отладки сбоя. Например, у меня произошел сбой на этапе 3 при обработке файла «x».
  2. Проверить, доступны ли определенные области памяти. Это было в основном для удовлетворения API для встроенной системы. Мы попытались бы записать в область памяти и поймать segfault, который сообщил нам, что память доступна только для чтения.
  3. Segfault обычно возникает из-за сигнала от MMU, который используется операционной системой для подкачки страниц памяти, если это необходимо. Если у ОС нет этой страницы памяти, она перенаправляет сигнал в приложение.
person Chris Arguin    schedule 23.12.2009

Ошибка сегментации действительно обращается к памяти, на доступ к которой у вас нет разрешения (либо потому, что она не отображается , у вас нет разрешений, неверный виртуальный адрес и т. д.).

В зависимости от основной причины вы можете захотеть перехватить и обработать ошибку сегментации. Например, если вашей программе передан недопустимый виртуальный адрес, она может зарегистрировать этот segfault, а затем выполнить некоторый контроль повреждений.

Segfault не обязательно означает, что куча программы повреждена. Чтение неверного адреса (например, нулевого указателя) может привести к segfault, но это не означает, что куча повреждена. Кроме того, приложение может иметь несколько куч в зависимости от среды выполнения C.

person kervin    schedule 23.12.2009
comment
@kervin: какой контроль повреждений? к тому времени куча может быть кучей хлама - person Alon; 24.12.2009
comment
@Alon: отредактировано для ответа на ваш вопрос. Segfault не обязательно означает, что куча повреждена. Кроме того, ваш обработчик не обязательно должен использовать ту же кучу или адресное пространство, на которое влияет segfault. - person kervin; 24.12.2009
comment
Ошибки сегментации использовались подходами алгоритмов сборки мусора для установки барьера в конце кучи, когда доступ и доставка sigsegv являются признаком того, что необходимо выполнить сборку мусора. - person Christian; 24.12.2009

Существуют очень продвинутые методы, которые можно реализовать, перехватив ошибку сегментации, если вы знаете, что ошибка сегментации не является ошибкой. Например, вы можете защитить страницы, чтобы вы не могли их читать, а затем перехватить SIGSEGV, чтобы выполнить «волшебное» поведение до завершения чтения. (См. Tomasz Węgrzanowski "Segfaulting собственные программы для развлечения и прибыль" в качестве примера того, что вы могли бы сделать, но обычно накладные расходы довольно высоки, поэтому это не стоит делать.)

Аналогичный принцип применяется к перехвату исключения недопустимой инструкции (обычно в ядре) для эмуляции инструкции, которая не реализована на вашем процессоре.

person Ken Bloom    schedule 26.04.2010

Например, для регистрации трассировки стека сбоя.

person Alex B    schedule 23.12.2009

Нет. Я думаю, что это пустая трата времени - ошибка сегмента указывает на то, что в вашем коде что-то не так, и вам будет лучше найти это, изучив дамп памяти и/или ваш исходный код. Один раз, когда я попытался отловить ошибку seg, я попал в зеркальный зал, которого я мог бы избежать, просто подумав об исходном коде. Никогда больше.

person Community    schedule 23.12.2009