LINUX.ORG.RU

defer в C быть!

 ,


0

9

Привет, ЛОР!

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

На днях данное предложение получило официальный статус и, скорее всего, defer появится в будущем стандарте C2y.

При этом, defer почти наверняка не будет добавлен в C++, так как его использование будет конфликтовать с другими частями этого языка.

Ссылка на пост в блоге автора: https://thephd.dev/c2y-the-defer-technical-specification-its-time-go-go-go

Спецификация: https://thephd.dev/_vendor/future_cxx/technical%20specification/C%20-%20defer/C%20-%20defer%20Technical%20Specification.pdf

Ответ на: комментарий от Iron_Bug

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

Ух ты, капча попросила выбрать колесо.
Выбрал вертолёт.
Всё ok!

anonymous
()
Ответ на: комментарий от alysnix

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

Вопрос, вы всё ещё готовы утверждать, что

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

?

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

Ух ты, капча попросила выбрать колесо. Выбрал вертолёт. Всё ok!

все логично. Колесо круглое и вертится. и это верчение роднит его с вертолетом. это какая-то ИИ капча.

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

я тоже не поняла. godbolt на моём браузере не работает, я не вникала, почему. но тот кусок кода, который приведён в посте, точно не соответствует ассемблерному выхлопу.

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

Замечательная!
Вообще не читаю, что она там просит.
Выбираю что попало и обычно с третьего раза всё ok!

anonymous
()
Ответ на: комментарий от Iron_Bug

godbolt на моём браузере не работает

unC0Rr@host /tmp> cat 1.c
int test(int a, int b) {
    if (b < 0) return 0;
    if (a + b < a) return 1111;
    return 31337;
}
unC0Rr@host /tmp> gcc -S -O2 1.c
unC0Rr@host /tmp> cat 1.s
	.file	"1.c"
	.text
	.p2align 4
	.globl	test
	.type	test, @function
test:
.LFB0:
	.cfi_startproc
	movl	%esi, %eax
	sarl	$31, %eax
	notl	%eax
	andl	$31337, %eax
	ret
	.cfi_endproc
.LFE0:
	.size	test, .-test
	.ident	"GCC: (Debian 12.2.0-14) 12.2.0"
	.section	.note.GNU-stack,"",@progbits

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

Это всё вершина айсберга.
Вот когда начнём обсуждать эксплойты, то тогда весело будет.

anonymous
()
Ответ на: комментарий от unC0Rr

там было еще утверждение, позже. что они все UB свалили в одну кучу, не предоставив никакой классификации.

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

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

я кстати начинал свое программирование с modula-2. там такого не было. там было исключение в таких вот случаях.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от unC0Rr
movl	%esi, %eax
sarl	$31, %eax
notl	%eax
andl	$31337, %eax
ret

это неправильный код. так писать нельзя!

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

Принял решение.
Больше постить не буду.
Разговоры не о чём, отвлекают от разработки.

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

Когда знаешь тип переменной из названия - это удобно

А потом ты поменял тип и надо переименовывать всё в коде. Особенно хорошо git blame потом выглядит от такого.

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

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

Потому что есть два стула: one’s complement и two’s complement. На какой сам сядешь, на какой мать родную посадишь?

Когда стандарт высра^Wродили, платформы с one’s complement арифметикой ещё кем-то использовались.

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

ты вроде говорил, что вызов должен вернуть 1111, но никак не получается попасть в эту ветку: если ты хочешь, чтобы a+b < a, то либо a>0 и и b<0, либо переполнение, когда а близко к INT_MIN и b<0, но в обоих случаях b<0 и ты не попадёшь в эту проверку, так как вывалишься раньше, при проверке b<0. как-то так.

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

эээ... не поняла. какие эскплоиты? эксплоиты чего?

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

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

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

try finally гарантирует, что код в finally будет выполнен в любом случае.
а с этим defer то же самое, но код должен обязательно быть деструктором.
Ну в чём разница-то?

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

Последнюю строку читать, как a + b < a

anonymous
()
Ответ на: комментарий от Shushundr

try finally гарантирует, что код в finally будет выполнен в любом случае.

ну идея примерно похожа. но там это некий блок что исполнится после перехвата исключения и его обработки(или необработки).

а с этим defer то же самое, но код должен обязательно быть деструктором.

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

а так, там можно даже биткоин майнить и посылать приветы теще в телеграмм.

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

нашла: у gcc есть опция -fwrapv, которая отменяет оптимизацию без учёта переполнения. если её добавить, всё будет работать нормально, с любым -Ox.

на самом деле, достаточно даже такого кода:

        int a = 0x77359400;
        int b = 0x77359400;
        int c = a+b;
        printf("%d\t%d\t%d\t%d\n", a+b, a, a+b<a, c<a);
интересные результаты с и без опции -fwrapv.

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

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

а что, на твой код надо смотреть именно тем глазком?

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

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

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

а когда он просто рубает код лопатой и делает не пойми что странное - это неприемлемо.

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

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

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

Что тут не зависит от компилятора и как железо должно перехватить ситуацию и вернуть 1111

По идее для такого кода надо отключать оптимизацию?

#pragma GCC push_options
#pragma GCC optimize ("O0")

int test(int a, int b) {
    if (b < 0) return 0;
    if (a + b < a) return 1111;
    return 31337;
}

#pragma GCC pop_options

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

ну, по идее компилятор приводит их к long и сравнивает.

С какой стати?

и пипец. чтобы этого не было, вот есть опция, оказывается.

Пипец – это то, что ты только сейчас об этом узнаёшь. Сишник с 30-летним стажем, ага.

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

Шоколадным?

у тебя код на расте что-ли?

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

и ещё есть флаг, который вызывает SIGFPE, если произошло такое переполнение: https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Signed-Overflow...

и ещё есть специальные встроенные функции с проверкой: https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html

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

я предполагаю, что gcc делает так при оптимизации. так-то в С99 это UB (думаю, что более поздние стандарты вряд ли переписали такое поведение), но gcc предлагает флаг, чтобы оно урезалось и не было UB. хотя лучше такое не использовать, как я уже написала.

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

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

скорее всего, в ядре этот флаг установлен на всякий случай, для лучшей защиты от дурака. это не значит, что надо использовать переполнения.

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

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

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

вообще, если есть подозрение, что какие-то типы будут меняться, то лучше сделать typedef. но венгерская нотация безобразна и с typedef и без него.

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

А кто сказал, что венгерскую нотацию надотиспользовать там, где она не принята? Речь идёт о проектах, принявших её как кодстайл.
Интересно кстати, есть ли какой-нибудь линтер, проверяющий соответствие венгерки реальным типам?

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

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

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

Видимо, между windows и posix, правда, c11threads очень медленно внедряется и его ни в windows ни в linux нет (или не было до недавнего времени)
Но главное здесь что стандарт теперь не предполагает существования только одной единственной нити исполнения, ранее это подразумевалось, а любые потоки включая posix уже определяли поведение самостоятельно за пределами стандарта C

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

любые потоки включая posix уже определяли поведение самостоятельно за пределами стандарта C

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

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

Сложнось именно в многопоточных кернелах под GPU - они обычно не запускают и останавливают потоки в произвольные моменты, а именно работают все сразу параллельно. То есть в gpu под многопоточностью подразумевается что-тотболее похожее на openmp или compute шейдер, а не pthreads.
К тому же в gpu помимо распараллеливания по ядрам есть ещё и распараллеливание по SIMD
Очевидно, что изнечально не написанный под gpu или openmp код не всегда легко или вообще возможно распараллелить

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

У них есть noscript версия, но она не удобная, а скриптовая версия уже нигде кроме хрома и его друзей не работает. Разраб pale moon уже задолбался исправлять работу их говнокода - в итоге оно там наполовину работает, но код не рисуется.
https://godbolt.org/noscript/z/1qens9jYd

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

ну, в силу отличия GPU от CPU, там вообще разные подходы к «параллельности». GPU, как и FPGA или DSP параллельно исполняют векторные операции. а в CPU есть некоторые попытки очередей и векторные инструкции, но это не тот масштаб и не те скорости. это просто вообще разные вещи. параллельность чаще нужна для обработки сигналов, звука, графики. хотя некоторую примитивную математику там тоже можно считать. именно поэтому фанаты виртуальных фантиков просаживают мегаватты впустую.

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

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

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

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

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

Очевидно, что изнечально не написанный под gpu или openmp код не всегда легко или вообще возможно распараллелить

Маленький комментарий.

Суперскалярность с выполнением вне очереди в современных процессорах. И Эльбрус с vliw, который не взлетел как gpu.

anonymous
()
Ответ на: комментарий от superuser

Аватарка прекрасно соответствует его комментариям, что здесь не так?

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

Да и просто под SIMD компилятор иногда может проанроллить и провекторизировать циклы. Но в данном контексте это скорее не благодаря языку, а вопреки

mittorn ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)