2015-04-04 4 views
1

вопрос у меня есть:Override сбоя в C++

Есть ли способ вызова функции или делать другую работу всякий раз, когда происходит сбой в программе.

Конкретно, код, который я в настоящее время работает, дает «segmentation fault» на очень большом входе. Это означает, что в какой-то момент я получаю доступ к некоторой недоступной \ нераспределенной части памяти. Отображение каждого шага было бы слишком неприятным, поэтому я хочу определить, когда я пересекаю границы.

Как это можно сделать?

+1

Почему не просто запустить свой код под Valgrind для того, чтобы найти и исправить ошибку (s)? –

+2

«Я хочу определить, когда я пересекаю границы» не связан с «вызовом функции или выполнением какой-либо другой работы всякий раз, когда происходит сбой». Использование отладчика хорошо для первого. Последнее, с точки зрения C++, является функциональностью для режима общего неопределенного поведения, и в этом режиме ничто не может быть гарантировано стандартом C++. Однако для нормального завершения, в том числе для неперехваченного исключения, у вас есть 'std :: terminate'. –

+0

да (я вижу, что это своего рода unix) - скомпилировать с включенной отладкой (cc -g ...), затем запустить с помощью gdb: gdb --args ./program , затем запустить –

ответ

1

Это конкретная операционная система и ее реализация. Практически также зависит от флагов компилятора и оптимизации.

Возможно, вы поразили undefined behavior.

Возможно, valgrind должен быть полезным инструментом.

Если на Linux, читайте core(5) & proc(5) & signal(7). Вы можете настроить общесистемный псевдо-файл /proc/sys/kernel/core_pattern, чтобы запустить внешнюю программу или сценарий (возможно, начать отладчик) на дампе ядра.

Вы можете обрабатывать сигнал SIGSEGV в зависимости от процессора и операционной системы. Но я не рекомендую этого. См. this & that ответы для получения дополнительной информации.

В Linux системных вызовов (перечисленные в syscalls(2)) являются почти единственными функциями, вы можете вызвать внутри обработчика сигналу (точнее, это функции асинхронного сигнала безопасных упомянутых в signal(7) и ничего более). Но многие функции библиотеки (включая malloc & printf, fprintf, dlopen и т. Д.) Запрещены внутри обработчиков сигналов.

1

Если вы скомпилировали код с помощью отладочных символов, вы должны либо загрузить файл ядра в ваш отладчик, либо прикрепить отладчик при возникновении сбоя.

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

1

Вам действительно нужен отладчик. Но чтобы ответить на исходный вопрос для будущих искателей:

Да, в UNIX вы можете просто обрабатывать сигнал SEGV с помощью обычных процедур обработки сигналов. SIGSEGV имеет номер 13. См. this о том, как обращаться с сигналами.

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

Я не рекомендую делать это в рабочем коде, но я думаю, что эта функция является «Unix путь» достаточно упомянуть о SO

+0

syscalls разрешены (в Linux) внутри обработчики сигналов. Но многие функции запрещены. См. Мой ответ. –