Код для преднамеренного сбоя

Возможный дубликат:
Каков самый простой способ вызвать сбой программы на C ++?

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

if(<something is wrong>)
{
    int *ptr = NULL;
    *ptr = 0;
}

Это, конечно, вызывает исключение нулевой ссылки и приводит к сбою программы без возможности восстановления. Мне просто интересно, действительно ли это лучший способ сделать это? Во-первых, он плохо читается. Без комментария вы можете не понять, что сбой, который здесь происходит, является преднамеренным. Во-вторых, от этого практически невозможно избавиться. Он не генерирует исключения, поэтому не может быть обработан другим кодом. Он просто убивает программу без возможности возврата. Это также не дает большого представления о том, почему здесь произошел сбой. И он вылетает во всех сборках, в отличие, скажем, от assert. (У нас есть довольно надежная система утверждений, но она не всегда используется в подобных случаях.)

Это стиль, который мы используем повсюду, и я не могу никого убеждать в обратном. Мне просто любопытно, насколько это распространено в отрасли.


person Darrel Hoffman    schedule 21.11.2012    source источник
comment
Почему бы просто не использовать abort()?   -  person Fred Larson    schedule 22.11.2012
comment
Я подозреваю, что намерение исходного программиста состоит в том, чтобы вызвать отказ программы без возможности восстановления при запуске в производственной ситуации или вызвать прерывание работы отладчика (если он присутствует). Мне не нравится эта конструкция, но я видел, как люди утверждали, что это единственный надежный кроссплатформенный способ добиться такого эффекта. Лично я бы не стал его использовать.   -  person Nik Bougalis    schedule 22.11.2012
comment
Это ужасно. Если вы знаете, что программа работает с ошибкой, но не знаете, почему, вам следует сбросить все, что, по вашему мнению, поможет решить проблему. Заставить программу вылететь без каких-либо подсказок относительно того, что произошло, - это ковбойское программирование ИМХО ...   -  person Robbie Dee    schedule 22.11.2012
comment
В C ++ нет такой вещи, как исключение нулевой ссылки.   -  person Kerrek SB    schedule 22.11.2012
comment
@RobbieDee: Ковбойское программирование - это то же самое, что и наступательное? :-)   -  person Kerrek SB    schedule 22.11.2012
comment
похоже, вопрос больше в том, как научить мои коллеги программировать? (потому что я думаю, что все могут согласиться, что они делают это неправильно)   -  person Shep    schedule 22.11.2012
comment
Никто не хочет, чтобы код запускался вживую, но сделать его тихим сбоям просто невозможно. Представьте, что какой-то плохой сервисный центр пытается объяснить это клиенту: извините, иногда он просто дает сбой, но мы не знаем почему. Я предполагаю, что покупатель в конце концов пойдет ...   -  person Robbie Dee    schedule 22.11.2012
comment
Я должен добавить, что это работает на нескольких разных платформах (всех текущих игровых консолях), поэтому вполне возможно, что некоторые функции, такие как abort(), могут быть кроссплатформенными не во всех системах. Мы большая известная компания, и я здесь новенький, поэтому я склонен верить им на слово, что все обстоит так, как есть, не зря. Но я еще не слышал хорошего объяснения этому.   -  person Darrel Hoffman    schedule 22.11.2012
comment
@KerrekSB: Или как там это называется. Я работаю на Java, поэтому я привык называть это исключением с нулевой ссылкой. Думаю, технически это не исключение, иначе я бы его поймал и не было бы проблем ...   -  person Darrel Hoffman    schedule 22.11.2012


Ответы (3)


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

throw string("something_went_wrong");

Еще лучше, если ошибка будет обнаружена или исправлена. Assert также будет прекрасным выбором.

person PearsonArtPhoto    schedule 21.11.2012
comment
В последнее время я слишком много программировал на java ... В любом случае, изменил пример на что-то получше. - person PearsonArtPhoto; 22.11.2012
comment
Нет, исключение - это совсем другое дело. Цель исключения - вызвать необычную ошибку, после которой приложение может восстановиться, в этом случае цель состоит в том, чтобы убить приложение, когда оно не может восстановиться. - person David Rodríguez - dribeas; 22.11.2012
comment
Неперехваченное исключение будет вести себя аналогично текущему поведению, с добавленным бонусом, который легче обнаружить, может дать более значимую трассировку стека и в более позднее время может быть исправлено путем перехвата ошибки. - person PearsonArtPhoto; 22.11.2012
comment
Я проголосовал за это специально, потому что OP упомянул его код ... не генерирует исключение, поэтому он не может быть обработан другим кодом. - person Fred Larson; 22.11.2012

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

Стандартный способ завершить выполнение - через std::terminate; обычный способ добиться этого - вызвать std::abort, который вызывает неблокируемый сигнал против процесса (автоматически приводит к std::terminate), а также заставляет многие операционные системы создавать дамп ядра.

person Kerrek SB    schedule 21.11.2012
comment
А разве не наоборот? std::terminate вызывает std::abort, который, в свою очередь, вызывает сигнал и т. Д. - person Danilo Piazzalunga; 22.11.2012
comment
@DaniloPiazzalunga: Нет, я так не думаю. Однако я нашел дополнительную информацию в стандарте: обычно не указано, вызывают ли неперехваченные сигналы раскручивание стека или нет, но вызов std::abort конкретно не вызывает раскручивание стека. (То есть это именно то, что нужно OP.) - person Kerrek SB; 22.11.2012
comment
На самом деле мы здесь не используем C ++ STL (или Boost, или любые другие сторонние библиотеки) - у нас есть собственный STL, поэтому вы не увидите std::anything в этой кодовой базе. Даже для струнных. Я не знаю, есть ли у него abort или terminate ... - person Darrel Hoffman; 22.11.2012

Я предполагаю, что это способ вызвать дамп ядра в ситуациях, когда вы не отлаживаете. Затем дамп ядра дает вам достаточно информации для анализа проблемы. В случае «ошибок программиста» (или ошибок) это лучше, чем выброс исключения, потому что раскрутка стека не позволит вам создать разумный дамп ядра. Подобного эффекта можно было бы достичь более элегантным способом, вызвав std :: terminate, предварительно зарегистрировав (с помощью std :: set_terminate) функцию, которая генерирует дамп ядра или что-то подобное. См. эту статью для более подробного объяснения.

person Andrzej    schedule 21.11.2012