Разница между Undefined Поведение и неправильное формирование, не требуется диагностическое сообщение

Стандарт С++ поставляется с потрясающим количеством определений для нечеткого поведения 1 которое означает более или менее то же самое с тонкими различиями. Чтение этого ответа, я заметил, что формулировка "программа плохо сформирована, не требуется диагностика".

Определенный реализацией отличается от неуказанного поведения тем, что реализация в первом случае должна четко документировать, что он делает (в последнем случае это не обязательно), оба они хорошо сформированы. Undefined поведение отличается от неуказанного тем, что программа ошибочна (1.3.13).
В противном случае у всех есть общее, что стандарт не делает никаких предположений или требований относительно того, что будет делать реализация. За исключением 1.4/8, в котором говорится, что реализации могут иметь расширения, которые не изменяют поведение хорошо сформированных программ, но плохо сформированы в соответствии со стандартом, а реализация должна диагностировать использование этих, но впоследствии может продолжить компиляцию и выполнение плохо сформированной программы.

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

Я был бы склонен думать, что слово "ошибочное" также подразумевает, что компилятор должен прервать сборку с сообщением об ошибке (в конце концов, ошибочно предполагает наличие ошибки), но раздел "Примечание" в 1.3.13 явно допускает что-то другое, включая молча игнорирование проблемы (и компиляторы явно не нарушают сборку из-за UB, большинство даже не предупреждают по умолчанию).

Можно также полагать, что ошибочные и плохо сформированные одинаковы, но стандарт не вникает в детали, если это так, или то, что должно означать это слово.

Далее, 1.4 утверждает, что

соответствующая реализация должна [...] принять и правильно выполнить хорошо сформированную программу

и

Если программа содержит нарушение правила, для которого не требуется диагностика, [...] нет требований к реализациям в отношении этой программы.

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

Во втором абзаце говорится, что что-либо в сочетании с "отсутствием необходимости диагностики" означает, что в спецификации нет требований, что означает, что он в основном эквивалентен "undefined поведению", за исключением того, что упоминание ошибочного не упоминается.

В чем заключалось бы намерение использовать формулировку, такую ​​как "плохо сформированная, не требующая диагностики"?

Наличие "никакой диагностики" предполагает, что оно идентично (или в основном идентично?) поведению undefined. Кроме того, поскольку поведение, определяемое реализацией и неопределенным, определяется как хорошо сформированное, оно должно быть чем-то другим.

С другой стороны, поскольку некорректная программа нарушает синтаксические/семантические правила, она фактически не должна компилироваться. Что, однако, в сочетании с "отсутствием необходимости диагностики" означало бы, что компилятору будет разрешено молча выйти без предупреждения, и после этого вы не сможете найти исполняемый файл.

Есть ли разница между "плохо сформированным, отсутствием диагностики" и "undefined поведением", или это просто сложный синоним для одного и того же?


1 В отсутствие лучшей формулировки для коллективного поведения

Ответ 1

Стандарт не всегда согласован, как хотелось бы, поскольку это очень большой документ, написанный (на практике) числом разных людей, и, несмотря на все доказательства, происходит, несоответствия проскальзывают. В случае undefined (и ошибки вообще), я думаю, что есть дополнительная проблема в том, что для большинства основных вещей (указатели и т.д.), стандарт С++ вдохновляет C. Но C понимает, что все ошибки undefined поведение, если не указано иное, где в качестве стандарта С++ пытается придерживаться точки зрения, что все ошибки требуют если не указано иное. (Хотя они все еще должны учитывать случай, когда стандарт не указывается поведение.) Я думаю, что это объясняет несогласованность в формулировке.

В глобальном масштабе несогласованность вызывает сожаление, но в целом, если в стандарте говорится, что что-то ошибочно или плохо сформировано, то это требует диагностики, если в стандарте не сказано, что это не является, или что это поведение undefined. В чем-то вроде "плохо сформирован, не требуется диагностика", "нет диагностических требуется ", потому что в противном случае это потребует диагностика. Что касается разницы между "плохо сформированными", нет "Требуется диагностика" и "undefined поведение", нет. Первое, вероятно, более часто встречается в случаях, когда код неверный, второй, где это проблема во время выполнения, но это не Систематическое. (Спецификация одного определения Правило, ясно, что проблема времени компиляции заканчивается на "then поведение undefined ".)

Ответ 2

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

В то время как плохо сформированный НДР является тем, что реализация должна диагностировать во время перевода, но может быть неспособна из-за различных технических или теоретических ограничений. Например. ODR потребует, чтобы реализация собирала все определения сущности и сравнивала их; но что массивный ресурс истощается. Некоторые вещи NDR даже вычислительно неосуществимы. undefined поведение возникает, когда реализация не сразу диагностирует этот материал.

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

Тем не менее, этот взгляд по-прежнему дает вам разумную идею о том, почему существуют два термина.