Но тогда получается, если трактовать UB именно так, как считаете вы, то по сути, любая ответственность по обработке UB, в том числе юридическая, перекладывается на производителя компилятора.
Почему "как считаю я"? Разве в стандарте неоднозначно написано?
В стандарте -- ни слова об ответственности, тем более, юридической. Если же говорить об "ответственности", то "ответственность" с компилятора в месте возникновения UB как раз снимается, причём абсолютно и полностью, чем современные компиляторы вовсю и пользуются.
Если уж говорить о чьей-то "ответственности", то имеет смысл говорить об "ответственности" программиста, ведь это он написал код с UB, к чему компилятор уж точно не имел ни малейшего отношения.
То есть клиент, получивший ущерб из за того, что компилятор некорректно обработал UB, теоретически вполне вправе требовать от производителя возмещения, ссылаясь на тот же стандарт. Ибо некорректное поведение компилятора в этом случае - проблема производителя.
Компилятор не имеет даже теоретической возможности неверно "обработать UB", ибо любая теоретически возможная "обработка" соответствует стандарту и поэтому является верной.
Неверная изначальная посылка о том, чья это ответственность, может далеко завести... но как правило не туда. Более того, вплетать вопросы юриспруденции в IT-шную сферу -- занятие неблагодарное, тем более, что в стандарте нигде нет ни намека на чью бы то ни было ответственность.
Насколько мне известно, сейчас лицензионные соглашения пишутся в стиле "компания <такая-то> никогда ни при каких условиях ни за что не будет отвечать". Поэтому мне странно видеть выводы о возможности требовать возмещения. Но это -- опять же, юриспруденция, к вопросу отношения не имеет.
Соответственно, изменение Control flow это проблема конкретного компилятора. Получается так.
Нет, получается не так.
Это проблема программиста, а не компилятора.
Компилятор в случае UB приобретает "абсолютные права" на всё, что угодно и что неугодно, в том числе, на нарушение Control flow, и никто не может ограничить его в этом "праве": для компилятора нет никого и ничего выше стандарта.
Кстати, компилятор не обязан "пользоваться" своими "абсолютными правами" на всё, что угодно и неугодно, и поэтому может создаться иллюзия, что компилятор, который ими в каком-то конкретном случае UB не воспользовался, "правильнее".
Нет, он -- не "правильнее", он просто -- "другее". Один ничем не лучше и не хуже другого, если пытаться сравнивать их по этому показателю.
UB допускает или не допускает программист без какого-либо участия в этом компилятора.
Компилятор в случае отсутствия UB теряет те самые "абсолютные права" на всё, что угодно и неугодно, в том числе, и "право" на нарушение Control flow.
Ну, что ж, придётся обратиться к последнему прибежищу интеллектуала, то есть, к первоисточнику (draft стандарта C++17):
3.27 [defns.undefined] undefined behavior behavior for which this document imposes no requirements
"Поведение, к которому данный документ не предъявляет вообще никаких требований" (форма отрицания с частицей "no" -- более жёсткая, чем просто отрицательная форма; в русском варианте она соответствует фразе, в которую добавлено слово "вообще" или "абсолютно").
Если к поведению не предъявлено вообще никаких требований, то такое поведение может быть абсолютно любым (это же верное логическое следование?).
По этой причине я принципиально не могу трактовать понятие UB "слишком вольно", потому что не существует ещё более вольной трактовки по сравнению с "не предъявляет вообще никаких требований". То есть, возможность трактовать понятие UB слишком вольно у меня отсутствует даже теоретически, не говоря уже о практике.
В данном примере UB относится только к значению переменной. Весь остальной код полностью валиден согласно стандарта и должен исполняться соответственно.
С момента возникновения UB не имеет никакого значения степень валидности остального кода.
Вы пытаетесь предъявить требования к коду на поведение при UB, когда утверждаете, что "... остальной код полностью валиден согласно стандарта и должен исполняться соответственно". "Код должен" -- это прямое требование к некоторому определённому поведению кода при данном UB.
Однако в библии стандарте прямо указано, что "данный документ не предъявляет вообще никаких требований" на поведение кода при UB. Поэтому требование "код должен" как минимум "нестандартно" и, поэтому, "необязательно к исполнению" компилятором при генерации кода (подразумевается, что мы обсуждаем "стандартные" компиляторы, то есть, те, которые "действуют" в соответствии со стандартом).
Что касается control flow violation, это уже указывает, как правило, на серьёзные ошибки в компиляторе.
Характерно, что как только UB в том моём случае был устранён, так control flow violation сразу же исчез совершенно чудесным и непостижимым образом.
Кстати, control flow violation "укладывается" в допустимое поведение при UB, поэтому, выходит, что компилятор в том случае был абсолютно прав.
Чтение из неинициализированной переменной подразумевает Undefined Behavior по отношению к возвращаемым данным (Data arbitrary), но не Control flow violation.
В стандарте понятие UB трактуется значительно шире, при этом UB не делится на подвиды. Там нет таких понятий как "UB по отношению к возвращаемым данным" или "Control flow violation".
С UB, приводящем к "Control flow violation", я сталкивался лично, правда, на C.
должен вернуть целое число в диапазоне от 0 до 2550. Потому что значение х не определено, Но явно определён его диапазон и операции над ним. И в целях оптимизации компилятор имеет право всегда возвращать, скажем, 0 или 1000. Но никогда -1. Это будет некорректным поведением априори.
Это больше похоже на Unspecified Behavior. В случае же UB результирующая программа, если скомпилировалась, имеет в месте возникновения UB поистине безграничные полномочия: может не только вернуть любое значение , но даже не вернуть никакое, например, завершившись.
Потому что чтение из неинициализированной переменной есть Undefined Behavior.
А UB подразумевает под собой любое поведение скомпилированного, в результате, кода.
Поскольку компилятор обычно стремится максимально соптимизировать код, в данном случае он соптимизировал его до простого возврата 0. Результирующее поведение кода после такой оптимизации вписывается в рамки UB, поскольку UB -- это любое поведение.
Хакер не может иметь деструктивное поведение по определению, иначе это не хакер.
Деструктивность поведения характерна как раз для крякера.
Это закреплено в соответствующем документе RFC-1983 (и в устаревшем RFC-1392). Хотя эти документы и не имеют статуса стандартов, но тем не менее:
hacker
A person who delights in having an intimate understanding of the
internal workings of a system, computers and computer networks in
particular. The term is often misused in a pejorative context,
where «cracker» would be the correct term. See also: cracker…
…
cracker
A cracker is an individual who attempts to access computer systems
without authorization. These individuals are often malicious, as
opposed to hackers, and have many means at their disposal for
breaking into a system. See also: hacker, Computer Emergency
Response Team, Trojan Horse, virus, worm.
Попробуйте самостоятельно найти информацию о том, в чём заключается принципиальное отличие линейки Windows 95/Windows 98/Windows Me от линейки Windows NT/Windows 2000/Windows XP/Windows Vista/Windows 7…
Замечу, что Windows 95 и Windows 98 сосуществовали с Windows NT, а Windows Me — с Windows 2000.
Почему "как считаю я"?
Разве в стандарте неоднозначно написано?
В стандарте -- ни слова об ответственности, тем более, юридической.
Если же говорить об "ответственности", то "ответственность" с компилятора в месте возникновения UB как раз снимается, причём абсолютно и полностью, чем современные компиляторы вовсю и пользуются.
Если уж говорить о чьей-то "ответственности", то имеет смысл говорить об "ответственности" программиста, ведь это он написал код с UB, к чему компилятор уж точно не имел ни малейшего отношения.
Компилятор не имеет даже теоретической возможности неверно "обработать UB", ибо любая теоретически возможная "обработка" соответствует стандарту и поэтому является верной.
Неверная изначальная посылка о том, чья это ответственность, может далеко завести... но как правило не туда. Более того, вплетать вопросы юриспруденции в IT-шную сферу -- занятие неблагодарное, тем более, что в стандарте нигде нет ни намека на чью бы то ни было ответственность.
Насколько мне известно, сейчас лицензионные соглашения пишутся в стиле "компания <такая-то> никогда ни при каких условиях ни за что не будет отвечать". Поэтому мне странно видеть выводы о возможности требовать возмещения. Но это -- опять же, юриспруденция, к вопросу отношения не имеет.
Нет, получается не так.
Это проблема программиста, а не компилятора.
Компилятор в случае UB приобретает "абсолютные права" на всё, что угодно и что неугодно, в том числе, на нарушение Control flow, и никто не может ограничить его в этом "праве": для компилятора нет никого и ничего выше стандарта.
Кстати, компилятор не обязан "пользоваться" своими "абсолютными правами" на всё, что угодно и неугодно, и поэтому может создаться иллюзия, что компилятор, который ими в каком-то конкретном случае UB не воспользовался, "правильнее".
Нет, он -- не "правильнее", он просто -- "другее". Один ничем не лучше и не хуже другого, если пытаться сравнивать их по этому показателю.
UB допускает или не допускает программист без какого-либо участия в этом компилятора.
Компилятор в случае отсутствия UB теряет те самые "абсолютные права" на всё, что угодно и неугодно, в том числе, и "право" на нарушение Control flow.
Вот, как получается.
Ну, что ж, придётся обратиться к последнему прибежищу интеллектуала, то есть, к первоисточнику (draft стандарта C++17):
"Поведение, к которому данный документ не предъявляет вообще никаких требований" (форма отрицания с частицей "no" -- более жёсткая, чем просто отрицательная форма; в русском варианте она соответствует фразе, в которую добавлено слово "вообще" или "абсолютно").
Если к поведению не предъявлено вообще никаких требований, то такое поведение может быть абсолютно любым (это же верное логическое следование?).
По этой причине я принципиально не могу трактовать понятие UB "слишком вольно", потому что не существует ещё более вольной трактовки по сравнению с "не предъявляет вообще никаких требований". То есть, возможность трактовать понятие UB слишком вольно у меня отсутствует даже теоретически, не говоря уже о практике.
С момента возникновения UB не имеет никакого значения степень валидности остального кода.
Вы пытаетесь предъявить требования к коду на поведение при UB, когда утверждаете, что "... остальной код полностью валиден согласно стандарта и должен исполняться соответственно". "Код должен" -- это прямое требование к некоторому определённому поведению кода при данном UB.
Однако в
библиистандарте прямо указано, что "данный документ не предъявляет вообще никаких требований" на поведение кода при UB. Поэтому требование "код должен" как минимум "нестандартно" и, поэтому, "необязательно к исполнению" компилятором при генерации кода (подразумевается, что мы обсуждаем "стандартные" компиляторы, то есть, те, которые "действуют" в соответствии со стандартом).Характерно, что как только UB в том моём случае был устранён, так control flow violation сразу же исчез совершенно чудесным и непостижимым образом.
Кстати, control flow violation "укладывается" в допустимое поведение при UB, поэтому, выходит, что компилятор в том случае был абсолютно прав.
В стандарте понятие UB трактуется значительно шире, при этом UB не делится на подвиды. Там нет таких понятий как "UB по отношению к возвращаемым данным" или "Control flow violation".
С UB, приводящем к "Control flow violation", я сталкивался лично, правда, на C.
Это больше похоже на Unspecified Behavior. В случае же UB результирующая программа, если скомпилировалась, имеет в месте возникновения UB поистине безграничные полномочия: может не только вернуть любое значение
, но даже не вернуть никакое, например, завершившись.
Потому что чтение из неинициализированной переменной есть Undefined Behavior.
А UB подразумевает под собой любое поведение скомпилированного, в результате, кода.
Поскольку компилятор обычно стремится максимально соптимизировать код, в данном случае он соптимизировал его до простого возврата 0. Результирующее поведение кода после такой оптимизации вписывается в рамки UB, поскольку UB -- это любое поведение.
Деструктивность поведения характерна как раз для крякера.
Это закреплено в соответствующем документе RFC-1983 (и в устаревшем RFC-1392). Хотя эти документы и не имеют статуса стандартов, но тем не менее:
Не совсем по теме, но очень близко: туда «напихивают» и кое-что понятное.
Выражение
-3/3u*3
— беззнаковое, его значение близко кUINT_MAX
.Мнение трёх компиляторов по этому поводу — здесь.
Замечу, что Windows 95 и Windows 98 сосуществовали с Windows NT, а Windows Me — с Windows 2000.
Интуиции не прикажешь?
Чувство, всё-таки…