C-комитет удалил 45 случаев undefined behavior из стандарта

Reducing undefined behavior in the C language

Мартин Уэкер на Kernel Recipes рассказал, как C борется с undefined behavior: в черновике C2y уже убрано 45 из примерно 100 опасных мест. Компиляторы получают новые предупреждения, статические анализаторы и санитайзеры, а для полной memory safety потребуется либо дорогая проверка во время выполнения, либо формальная верификация.

Проблема, по словам Уэкера, в том, что стандарт позволяет компилятору делать что угодно в ответ на undefined behavior — вплоть до вызова носовых демонов.
  1. pizlonator

    Круто, что здесь упоминается Fil-C, но это ещё и недооценивает его. TFA также недооценивает CHERI. Fil-C не просто «находит много ошибок временной безопасности». Он закрывает ошибки безопасности памяти (пространственной и временной) для авторов эксплойтов и приписывает строгую семантику всему языку. CHERI идёт на некоторые другие компромиссы, но тоже даёт достаточно строгую семантику, чтобы эксплойты на безопасность памяти не работали. И CHERI, и Fil-C более всеобъемлющи, чем Rust, поскольку они атакуют проблему на уровне ABI (и поэтому вы не получаете проблему, когда защита применяется только к тем частям, которые были переписаны на безопасном подмножестве нового языка). Rust можно было бы назвать лучшим в плане времени компиляции, но это не имеет существенного значения, если вас беспокоит определённость семантики или эксплуатируемость.

  2. chasil

    «Некоторые машины Honeywell, например, имели девятибитные байты.»

    OS 2200 имеет 36-битные слова. Это всё ещё поддерживаемая платформа.

    https://en.wikipedia.org/wiki/UNIVAC_1100/2200_series

    Эта платформа была первой реализацией SMP UNIX:

    «Любая конфигурация, поставляемая Sperry, включая многопроцессорные, может работать под управлением системы UNIX.»

    https://www.nokia.com/bell-labs/about/dennis-m-ritchie/other...

  3. vrighter

    я вообще-то думал начать шуточный проект, который сделал бы UB действительно UB. не в смысле «на практике знаковое переполнение на большинстве современных CPU обрабатывается одинаково». я имею в виду RNG и систему плагинов для компилятора, чтобы вводить новые B в дополнение к U

  4. hn_submit

    Полагаю, это не туда копает, поскольку, ИМХО, C — это просто «высокоуровневый ассемблер» для системного программирования. Как только вы добавляете runtime-поведение для борьбы с неопределённым поведением (UB), вы взрываете время выполнения. А статический анализ может зайти лишь настолько далеко, не взрывая время компиляции.

    C — это «правильный инструмент для правильной задачи», а именно операционные системы и их код, который вызывается тысячи раз в секунду. Вы не можете позволить себе ни единой йоты runtime-проверок в таком коде. Разработчик должен знать, что делает, или ему следует уйти с кухни.

    Нам следует отговаривать от использования C в прикладном программировании и подталкивать прикладных разработчиков к безопасным языкам вроде Rust или Go.

    И я даже не уверен, решает ли Rust этот случай с точки зрения UB.

  5. rwmj

    Думаю, стоит хотя бы упомянуть https://en.wikipedia.org/wiki/CompCert, хотя это и не свободное ПО (лицензия «исходники доступны»). Именно так компании, у которых есть большие кодовые базы на C в отраслях, критичных для безопасности, верифицируют свой код.

  6. vbezhenar

    Моя главная претензия к UB в C — то, что оно молчаливое.

    Я не против, чтобы компилятор делал дикие вещи, ладно, как угодно. Ну, я не то чтобы не против, но могу смириться в этом безумном мире.

    Но я хочу громких предупреждений! Вроде WARNING: этот условный оператор был свёрнут в одну ветку, потому что более раннее деление на ноль — это UB. И тогда я могу это заметить и переписать или просто убрать это условие.

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

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

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

  7. 1vuio0pswjnm7

    1790620504 | Reducing undefined behavior in the C language | https://lwn.net/SubscriberLink/1095811/b9325731ea9b61e0/ | https://news.ycombinator.com/item?id=49882419 | 15 comments

    1790673092 | Reducing undefined behavior in the C language | https://lwn.net/SubscriberLink/1095811/efcdbcf080cfa4c6/ | https://news.ycombinator.com/item?id=49890290 | 0 comments

  8. p1necone

    Концепция неопределённого поведения, специфичная для C/C++, всегда казалась мне совершенно безумной, и я до сих пор не читал ничего, что заставило бы её казаться менее безумной.

Ещё за этот день

2026-10-09