Есть ли смысл ловить «сегфо»? - PullRequest
5 голосов
/ 24 декабря 2009

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

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

Ответы [ 6 ]

15 голосов
/ 24 декабря 2009

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

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

Так что, в общем, нет смысла его ловить и делать что-либо, ЗА ИСКЛЮЧЕНИЕМ, завершающим процесс довольно резким образом. Нет смысла пытаться записывать (важные) данные обратно на диск или продолжать выполнять другую полезную работу. Есть некоторый смысл в выгрузке состояния в журналы - что делают многие приложения - и затем в выходе.

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

13 голосов
/ 24 декабря 2009

Ряд причин:

  1. Чтобы предоставить больше информации о приложении для отладки сбоя. Например, я потерпел крах на этапе 3, обрабатывая файл 'x'.
  2. Чтобы проверить, доступны ли определенные области памяти. Это было главным образом для удовлетворения API для встроенной системы. Мы попытаемся записать в область памяти и поймать ошибку, которая говорит нам, что память доступна только для чтения.
  3. Segfault обычно исходит из сигнала от MMU, который используется операционной системой для замены страниц памяти в случае необходимости. Если ОС не имеет этой страницы памяти, она передает сигнал в приложение.
6 голосов
/ 24 декабря 2009

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

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

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

5 голосов
/ 26 апреля 2010

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

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

1 голос
/ 24 декабря 2009

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

0 голосов
/ 24 декабря 2009

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

...