LINUX.ORG.RU

Предложение по контролю неопределённого поведения в Си

 , , неопределённое поведение


0

5

Привет, ЛОР!

В конце прошлого года было опубликовано предложение по добавлению в язык Си конструкций для контроля и упреждения неопределённого поведения.

Ссылка: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3211.pdf

Для Ъ:

Предлагается добавить специальную прагму MEMORY_SAFETY с вариантами DYNAMIC, STATIC и OFF. При включении MEMORY_SAFETY STATIC все варианты UB превращаются в ошибки сборки. Также, запрещаются многие конструкции, которые могут вызывать неопределённое поведение, например, операции над знаковыми числами, которые могут вызвать переполнение. В случае DYNAMIC, код, вызывающий неопределённое поведение, будет выбрасывать ошибку во время выполнения.

Что думаешь, ЛОРовец? Позволит ли это программистам на Си наконец перестать портить память?

★★★★★

Последнее исправление: hateyoufeel (всего исправлений: 2)

Позволит ли это программистам на Си наконец перестать портить память?

лучше отобрать память у тех, кто ее портит, и вернуть тем, кто ее потерял. то есть вернуть память пенсионерам.

alysnix ★★★
()

Что-то аналогичное поведению c++ в constexpr функциях нужно.
В constexpr правда всё реализуется в компилтайме, а для реализации подобного в рантайме потребуются рантаймовые проверки

Позволит ли это программистам на Си наконец перестать портить память?

Нет конечно, желающие насрать каким-нибудь UB всегда найдутся, даже если возможность это сделать запрячут за семью печатями. Чего стоит проект на rust, использующий DefaultHash в сетевом протоколе... Запретили им срать в память, они в логику насрали

mittorn ★★★★★
()
Последнее исправление: mittorn (всего исправлений: 2)
Ответ на: комментарий от apt_install_lrzsz

выбрасывать ошибку во время выполнения

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

Ну и ладно, зато программа просто сразу упадёт, а не насрёт мимо буфера. Это уже будет намного лучше.

theNamelessOne ★★★★★
()
Ответ на: комментарий от mittorn

Что-то аналогичное поведению c++ в constexpr функциях нужно.

Например… constexpr?

https://en.cppreference.com/w/c/language/constexpr

Он в сишечке уже есть. Правда, как и всё в Си, урезанное до полного убожества. Функции в си не могут быть constexpr, например. Только переменные.

Нет конечно, желающие насрать каким-нибудь UB всегда найдутся, даже если возможность это сделать запрячут за семью печатями. Чего стоит проект на rust, использующий DefaultHash в сетевом протоколе… Запретили им срать в память, они в логику насрали

А где там UB? Присунуть рандом по сети – это не UB, это просто тупняк.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 2)

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

Так оно ж тогда будет определённым.

ya-betmen ★★★★★
()
Ответ на: комментарий от hateyoufeel

Я имею в виду поведение компилятора, когда он компилирует компилтаймовый вызов constexpr функции. В этом случае он не допускает никакие UB. Например, записать один член юниона, а прочитать другой нельзя. До c++20/23 не было способа получить битовое представление float/double - т.к все привычные способы это сделать - UB. Числовое значение указателя тоже нельзя получить, хотя указатели там есть. Доступ к массивам (в том числе через адресную арифметику) проверяется. Такой вот safe c++, жалко, только для constexpr

mittorn ★★★★★
()
Ответ на: комментарий от PPP328

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

mittorn ★★★★★
()
Ответ на: комментарий от eternal_sorrow

Да вычитание походу тоже :) и многое многое другое. безопасно посчитать в уме и положить по адресу, так и живем ;) можно абак взять и логлинейку, чтоб не так тоскливо было

Morin ★★★★★
()

Что думаешь, ЛОРовец? Позволит ли это программистам на Си наконец перестать портить память?

Алгоритм будет примерно такой:

  1. прописал MEMORY_SAFETY STATIC
  2. запустил компиляцию
  3. заплакал
Obezyan
()

Позволит ли это программистам на Си наконец перестать портить память?

Нет, конечно. UB причина не всех порч памяти. Я просто делаю баг с адресной арифметикой, и без всяких UB память переписывается где не надо. Или утечка памяти. Какое UB заставляет меня не освободить память в нужном месте?

seiken ★★★★★
()

Что-то мне кажется, что включение MEMORY_SAFETY для уже существующего проекта будет не менее интересным экспириенсом чем превращение того же проекта в MISRA-conform

alx777 ★★
()
Ответ на: комментарий от seiken

Я просто делаю баг с адресной арифметикой, и без всяких UB память переписывается где не надо.

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

Или утечка памяти. Какое UB заставляет меня не освободить память в нужном месте?

Утечка памяти не приводит к порче.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

и в рамках арифметики ты можешь только в пределах одного массива туда-сюда указатель катать

Или за пределами…

Утечка памяти не приводит к порче.

Хорошо, хрен с ней, утечкой. Как на счёт use-after-free?

seiken ★★★★★
()

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

vbr ★★★★★
()

варианты UB превращаются в ошибки сборки

Есть предложение получше. Для всех UB конкретный компилятор должен делать что-то конкретно задокументированное.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Для всех UB конкретный компилятор должен делать что-то конкретно задокументированное.

И что компилятор может задокументировать для

char * my_strcpy ( char * destination, const char * source ) {
  char * dst = destination;
  while (*dst++ = *source++);
  return destination;
}

которое было скомпилировано в .so и динамически подгружается?

«Может произойти запись в область памяти, расположенную после объекта выделенного по указателю destination, что может вызвать segmentation fault, нарушения логики программы, инъекцию произвольного кода и другие последствия»?

red75prim ★★★
()
Ответ на: комментарий от red75prim

И что компилятор может задокументировать для

То, что конкретно компилируется на конкретной платформе.

Может произойти запись в область памяти

Что значит может? Либо оно на конкретной платформе происходит, либо валится с каким-нибудь SIGBUS.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Либо оно на конкретной платформе происходит, либо валится с каким-нибудь SIGBUS.

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

monk ★★★★★
()

Что думаешь, ЛОРовец?

Немного непонятно, о чём идёт речь. О неопределённом поведении или о безопасности работы с памятью? Если первое, то давно пора. Лучше бы в опции компилятора это добавили, чтоб он как минимум выдавал предупреждение. Если второе, то хз.

Позволит ли это программистам на Си наконец перестать портить память?

Время покажет.

u5er ★★★
()
Ответ на: комментарий от monk

Зависит от того, что находится после этого объекта

Каким образом это относится к языку? Так что угодно можно объявить UB. Например

int a = 1

Где гарантия что будет достаточно памяти для этого? ОЛОЛО UB.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от goingUp

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

да там половина кода, это по его мнению - «память портить».

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Каким образом это относится к языку?

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

Где гарантия что будет достаточно памяти для этого?

Здесь есть гарантия, что или в переменную попадёт нужное значение или программа вообще не запустится. Для программы без UB можно строить математическое доказательство корректности.

Например для:

int f(int x)
{
  unsigned int a = x;
  a += 1;
  g(a);
  return a;
}

можно гарантировать, что f(x) вернёт x+1 для любого x.

А вот если где-то в программе есть UB, то g() может изменить значение a или даже сделать так, что f(x) вообще ничего не вернёт, а передаст управление в совсем другое место.

monk ★★★★★
()
Ответ на: комментарий от monk

Здесь есть гарантия, что или в переменную попадёт нужное значение или программа вообще не запустится

Нет такой гарантии, стек может в любой момент переполнится.

можно гарантировать, что f(x) вернёт x+1 для любого x.

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

Можно гарантировать утверждение «если f(x) что-то вернула, это что-то равно x+1».

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

может произойти что угодно при переполнении стека

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

monk ★★★★★
()
Ответ на: комментарий от monk

без UB, то переполнения стека быть не может

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

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

По твоим рассуждениям это зависит от внешних обстоятельств.

Также, как в любой функции, которая получает указатель и его разыменовывает.

По-моему это как-то странно, требовать от языка контролировать весь мир, в том числе и в будущем, а иначе UB.

Можно указывать требования, при которых UB гарантированно нет, что в Си и принято.

monk ★★★★★
()