Что такое неопределенное поведение на С++? Чем он отличается от поведения undefined?

В чем отличие поведения неопределенного и поведения undefined на С++? Является ли эта классификация действительной и для кодов C?

Ответы

Ответ 1

РЕДАКТИРОВАТЬ 1: Последние черновики C11 и С++ 11 доступны здесь: C11 draft N1570 и С++ 11 draft n3242, если у вас нет копии окончательных стандартов и замечательно, как они выглядят. (Другие изменения внешнего вида текста и некоторые редакционные/грамматические изменения были сделаны.)

РЕДАКТИРОВАТЬ 2: Исправлено все вхождения "поведения" в качестве "поведения" для соответствия стандарту.

При поиске в стандартах С++ 11 и C11 нет совпадений для неопределенного правила или правила undefined. Существуют такие термины, как неопределенное значение, неопределенно упорядоченное, неопределенное неинициализированное и т.д.

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

С++ опирается на определения C. Многие полезные определения, касающиеся типов поведения, можно найти в C11 Section 3 (на C11). Например, неопределенное значение определено в 3.19.2. Имейте в виду, что C11 Раздел 2 (Нормативные ссылки) предоставляет другие источники для дополнительной интерпретации терминов, а Раздел 4 определяет, когда происходят такие случаи, как поведение undefined в результате несоблюдения стандарта.

Раздел 3.4 C11 определяет поведение, 3.4.1 определяет поведение, определяемое реализацией, 3.4.2 определяет поведение, зависящее от локали, 3.4.3 определяет поведение undefined, 3.4.4 определяет неуказанное поведение. Для значения (раздел 3.19) существуют значения, определяемые реализацией, неопределенное значение и неопределенное значение.

Говоря кратко, термин неопределенный относится к неопределенному/неизвестному состоянию, которое само по себе не приводит к поведению undefined. Например, этот код С++ включает неопределенное значение: {int x = x; }. (Это на самом деле пример в стандарте С++ 11.) Здесь x определяется как целое число сначала, но в этой точке оно не имеет четко определенного значения - тогда оно инициализируется любым (неопределенным/неизвестным) значение имеет!

Известный термин undefined поведение определен в 3.4.3 в C11 и относится к любой ситуации a

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

Другими словами, поведение undefined - некоторая ошибка (в логике или состоянии), и все, что происходит дальше, неизвестно! Таким образом, можно сделать правило undefined [поведение], которое гласит: избегать поведения undefined при написании кода C/С++!: -)

Правило неопределенного [поведения] должно состоять в следующем: избегать написания неопределенного кода, если это необходимо, и это не влияет на правильность или переносимость программы. Поэтому, в отличие от поведения undefined, неопределенное поведение не обязательно означает, что код/​​данные ошибочны, однако его последующее использование может быть или не быть ошибочным - так как требуется забота о соблюдении правильности программы.

Другие термины, такие как неопределенные последовательности, содержатся в основном тексте (например, C11 5.1.2.3, пункт 3, С++ 11, раздел 1.9, пункт 13, то есть в [intro.executation]). (Как вы могли догадаться, это относится к неуказанному порядку рабочих шагов.)

IMO, если вас интересуют все эти нюансы, приобретение стандартов С++ 11 и C11 является обязательным. Это позволит исследовать желаемый уровень детализации, необходимый с определениями и т.д. Если у вас нет таких ссылок, приведенных здесь, вы сможете изучить их с последними опубликованными проектами стандартов C11 и С++ 11.

Ответ 2

Следующие замечания основаны на стандарте C, ISO-9899, а не на С++, но значения в принципе одинаковы ( см. разделы 3.4 и 4 стандарта C, см. также стандарт С++, ISO-14882, раздел 1.3, последний документ не определяет ' неуказанное значение "как таковое, но использует эту фразу позже с очевидным значением). Официальные документы стандартов не являются бесплатными (действительно, они дороги), но ссылки выше относятся к страницам комитетов и включают бесплатные" черновики" стандарта, которые вы можете принять, чтобы быть по существу эквивалентными окончательному стандарту.

Термины описывают лестницу неопределенности.

Итак, двигайтесь вниз.

В большинстве случаев стандарт определяет, что должно произойти в конкретном случае: если вы пишете c=a+b и a и b являются int, тогда c является их суммой (по модулю некоторых деталей), Это, конечно, точка стандарта.

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

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

Undefined поведение - самый экстремальный случай. Здесь все ставки отключены. Если компилятор или создаваемая им программа работает в undefined, он может делать все: он может скремблировать память, повреждать стек, HCF или, в стандартном крайнем случае, заставить демонов вылететь из вашего носа. Но в основном это просто сбой. И все эти поведения соответствуют стандарту. Например, если переменная объявлена ​​как static int i; и int i; в той же области видимости, или если вы пишете #include <'my file'.h>, эффект будет undefined.

Существуют аналогичные определения для "значения".

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

Значение, определенное реализацией, похоже на поведение, определяемое реализацией. Подобно неуказанному, это действительное значение, но документация по реализации должна зафиксировать себя на том, что будет возвращено, и делать то же самое каждый раз.

Неопределенное значение, еще более неопределенное, чем неопределенное. Это либо неопределенное значение, либо ловушка. Представление ловушки - это стандарты, говорящие о каком-то волшебном значении, которое, если вы пытаетесь присвоить его чему-либо, приводит к поведению undefined. Это не должно быть реальной стоимостью; вероятно, лучший способ подумать об этом - "если бы у C были исключения, представление ловушки было бы исключением". Например, если вы объявляете int i; в блоке без инициализации, начальное значение переменной i является неопределенным, что означает, что если вы попытаетесь присвоить это чему-то еще до его инициализации, то поведение undefined, и компилятор имеет право попробовать трюк с демоном - вне игры. Конечно, в большинстве случаев компилятор будет делать что-то менее драматичное/забавное, например, инициализировать его до 0 или другого случайного действительного значения, но независимо от того, что он делает, вы не имеете права на объект.

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

Изменить 1: уточнить неопределенные значения.

Изменить 2: включить ссылку на стандарт С++ и отметить, что проекты комитетов по существу эквивалентны окончательному стандарту, но свободны.

Ответ 3

Я думаю, что в стандарте упоминается поведение undefined и неопределенное значение. Итак, каждый говорит о поведении, а другой о значении.

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