LINUX.ORG.RU

В стандарт C предложено внести лямбды и defer из golang

 , ,


5

6

Привет, ЛОР!

Я тут тебе немного покушать принёс. Как ты, наверное знаешь, не за горами выход нового стандарта языка C – C23. Среди прочих вкусностей, таких как лямбды в стиле C++, в этот стандарт предложено добавить механизм defer, аналогичный существующему в языке Go.

Ссылка на предложение: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2895.htm

В случае, если этот стандарт будет принят, будет возможно написание вот такого кода:

p = malloc(N);
defer { free(p); }

Где аргументом оператора defer является анонимная функция. Так же возможны более сложные варианты использования:

enum { initial = 16, };
double buffer[initial] = { 0 };
...
size_t elements = 0;
double* q = buffer;
defer [orig = q, &q]{ if (orig != q) { free(q); }};
...
// increase elements somehow
...
// adjust the buffer
if (elements > initial) {
    double* pp = (q == buffer) ? malloc(sizeof(double[elements])) : realloc(q, sizeof(double[elements]));
    if (!pp) return EXIT_FAILURE;
    q = pp;
}
...

Учитывая всё это, скоро в C больше не будет нужно использовать goto вообще нигде, даже для очистки ресурсов при ошибке. Так заживём, ЛОР!

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

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

(void*)0, (void*)-1 тебя не смущают?

если хочешь переносимый код

Откуда взялось требование переносимости, если только что обсуждалась запись по адресу в регистры MMIO конкретного устройства?

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

Диванные железячники подтянулись.

Ага.

Программе может быть некуда падать.

Значит JMP на вечный цикл делаем. Что угодно, только не продолжать выполнение.

А если писать можно (и нужно) по любому адресу?

Не можно.

Может программист все-таки сам решит, где ему надо вставлять проверки, а где не надо?

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

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

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

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

Мне хочется, чтобы в программах на С не было глупых уязвимостей,

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

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

делать из него язык для программирования прикладного по - неверно. его назначение другое.

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

(void*)0, (void*)-1 тебя не смущают?

Ровно такой же невалидный в общем случае код.

Откуда взялось требование переносимости, если только что обсуждалась запись по адресу в регистры MMIO конкретного устройства?

Я не знаю, откуда. Меня спросили - как писать по конкретному адресу - я ответил. В рамках C - никак. В рамках gcc - без проблем.

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

Значит JMP на вечный цикл делаем. Что угодно, только не продолжать выполнение.

Отлично. Осталось научить компилятор угадывать, когда нужно делать JMP на вечный цикл, когда abort, а когда bad_dereference_exception выкидывать. Немного усилий, и будет почти

if (ptr >= lower_bound && ptr < upper_bound) {
    // ...
} else {
    // your_error_handler_of_choice
}

Не можно.

Отличная аргументация, спасибо!

Нельзя. Он тупой. Ему доверия нет.

Да, я знаю, что тебе Раст нравится.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от reprimand
  1. Для этих целей придумали intptr_t, на который все забили, потому что у всех и так всё работает. Я согласен, что это проблема - культуры кода, которая помимо прочего отвечает стандартам

intptr_t тебе ничего не гарантирует. Ровно такой же компиляторо-зависимый код. Да, если ты хочешь хранить указатель как число, ты обязан использовать intptr_t. Но если ты думаешь, что получится переносимый код, ты ошибаешься. Это implementation-defined.

  1. Покажи где это не работает. Нет, я не оправдываю п.1, мне реально интересно

Не покажу, я стандарт примерно знаю, а по экзотическим архитектурам не мастак. Но суть в том, что стандарт имеет нужную гибкость. Да и никто не мешает сделать intptr_t 128-битным и хранить там адрес+длину при касте. Вообще без проблем.

Legioner ★★★★★
()

Не вполне понятна мотивация этих предложений, особенно defer. Кому надо, тот может взять кресты. Необязательно сразу же начинать дрочить в присядку с шаблонами на шаблонах, можно простенькие классы катать, только ради RAII. С другой стороны эти defer привносят неявное поведение, т.е. а чем это лучше крестов тогда?

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

Тем не менее, 70% CVE – это ошибки работы с памятью. Такие дела.

То, что люди «завтыкали их» это не означает что надо полностью заменить язык. Аналог с log4j я привел

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

Есть более компетентные, которые знают о разных инструментах и методиках, которые помогают избежать подобных ситуаций:

1. Статический анализ (благо, сейчас дохрена разных инструментов и все они улучшаются)
2. clang -fsanitize
3. valgrind
4. редакторы кода с встроенным анализатором

Ты знаешь что используя уже этот короткий список ты можешь найти уйму проблем в уже используемом современном софте который все мы запускаем под linux?

Но всем пофиг. Фигак-фигак, и в продакшн.

Так что как по мне, это проблема в первую очередь менеджмента.

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

Отлично. Осталось научить компилятор угадывать, когда нужно делать JMP на вечный цикл, когда abort, а когда bad_dereference_exception выкидывать.

Да компилятору вообще пофиг. Может вызывать какой-нибудь __abnormally_stop_execution. А линкер по этому символу уже будет подкладывать нужную реализацию. Или флагом нужным переключать, что генерировать в этом случае. Это не та проблема, которую интересно обсуждать.

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

писать на нём компоненты прикладного ПО тоже вполне себе ничего

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

Ровно такой же невалидный в общем случае код.

Очень интересные наблюдения. Можете еще свое мнение по поводу mmap(addr, ...MAP_FIXED...) сообщить?

в общем случае

Никого не волнует «общий случай». В общем случае получается та самая абстрактная машина, которая ничего не делает. Нельзя написать даже хелловорлда, не использовав (пусть даже косвенно) те самые «невалидные в общем случае» частные случаи.

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

Я тоже более-менее знаю стандарт. К сожалению, в мире МК и всякой очень низкоуровнёвой хрени, нет возможности поступать иначе.

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

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

То, что люди «завтыкали их» это не означает что надо полностью заменить язык.

Почему не значит? Язык – это не что-то сверхценное. Не вижу причин почему нельзя этого сделать.

Аналог с log4j я привел

Один. Молодец. А теперь посчитай количество RCE в сишном коде.

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

Почему не значит? Язык – это не что-то сверхценное. Не вижу причин почему нельзя этого сделать.

Так почему до сих пор не заменили?

Ах да, нечем! Пытались-пытались, и так никто и не смог. Вот делов-то.

Один

Грусть ситуации состоит как раз именно в том, что не один...

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

Очень интересные наблюдения. Можете еще свое мнение по поводу mmap(addr, …MAP_FIXED…) сообщить?

А что именно хочется услышать? Не очень понимаю вопроса.

Никого не волнует «общий случай». В общем случае получается та самая абстрактная машина, которая ничего не делает. Нельзя написать даже хелловорлда, не использовав (пусть даже косвенно) те самые «невалидные в общем случае» частные случаи.

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

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

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

Так почему до сих пор не заменили?

Где не заменили? Там, где стояло реально большое бабло, много где заменили. Той же Ada, например. А лялексовое ведро пусть дальше падает.

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

Всё вышеперечисленное и так является неопределённым поведением.

Прекращай молиться на макулатуру.

Программист тупой, ему доверия нет.

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

И что по-твоему должен означать код (void*)12345

(void*)12345 это указатель на адрес 12345, полностью корректная конструкция в Си. Я не знаю, где ты вычитал что это UB, но даже если где-то и правда так написано - значит авторы того документа тебя обманули. Его можно, например, использовать так:

fputs((void*)12345, stdout);
Это означает, что надо вывести в stdout ASCIIZ-строку, прочитанную из памяти процесса начиная с адреса 12345, что бы там ни было.

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

Весь код на Си - компиляторно-зависимый, смирись.

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

Очень интересные наблюдения. Можете еще свое мнение по поводу mmap(addr, ...MAP_FIXED...) сообщить?

Всё равно по стандарту. Функция возвращает адрес на какой-то участок памяти, с указателем можно работать. И это не так важно что в качестве первого аргумента мы можем передать что угодно. Ведь это системный вызов. К тому же mmap может вернуть нам MAP_FAILED.

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

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

P.S. Кстати меня лично выбешивает, что адресная арифметика может быть ВНЕЗАПНО знаковой (привет шлангу), хотя по логике вещей - она беззнаковая.

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

Если для тебя Стандарт это макулатура, то ой.

Это не UB, это implementation defined behaviour. Т.е. конкретно в мануале gcc для конкретной платформы x86_64 может быть написано, что эта конструкция работает так, как ты написал. А в каком-нибудь компиляторе для web assembly она не будет работать, к примеру. И твой код получится непереносимым.

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

Прекращай молиться на макулатуру.

На эту мукулатуру молятся авторы компилятора, которым ты пользуешься.

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

Ты, кажется, совсем не понимаешь, что такое UB в C. Возможно, тебе и правда стоит писать на PHP, про который ты тут так много рассуждаешь.

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

P.S. Кстати меня лично выбешивает, что адресная арифметика может быть ВНЕЗАПНО знаковой

Куда там знак можно засунуть? Умножение над адресами не делается, а сложение/вычитание не зависит от знаковости.

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

а сложение/вычитание не зависит от знаковости.

ХАХАХАХАХАХАХАХАХ! Правда не зависит? И UB там в зависимости от наличия знака нигде не будет?

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

Понятия не имею, но шланг вот считает что в числовом представлении указатель - знаковый!

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

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

Пожалуйста, прочитай mmap(3), раздел про MAP_FIXED и интерпретацию параметра addr при этом флаге.

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

Я эту документацию наизусть знаю, в том числе про MAP_FIXED. Что сказать-то хотел?

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

каком-нибудь компиляторе для web assembly она не будет работать
И твой код получится непереносимым.

Я так расстроен (нет). Я не пишу для webassembly.

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

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

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

An example of undefined behavior is the behavior on integer overflow

Говорит нам всё от же любимый стандарт C.

В школу иди.

Зачем? Попроси свою мамку тебя забрать с продлёнки.

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

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

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

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

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

Можете еще свое мнение по поводу mmap(addr, …MAP_FIXED…) сообщить?

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

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

Наоборот. Стандарт - работает везде. Но если что-то работает везде - это не означает что это стандарт.

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

Я лишь говорю о том что вы говорите о разных вещах.

Есть стандарт в головах у людей. Например есть крикуны, которые говорят, что systemd - это стандарт. Ага, стандарт, у них в голове и у прихвостней одной корпорации.

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

Тоже так думаю, но есть же MAP_FAILED если вдруг что, верно?

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

Что такое «низкоуровневый» в твоём определении? Есть считать что это язык, в котором нужно помнить о деталях реализации в железе, то таких сейчас фактически нет из популярных.

Кроме ассемблеров, хотя и тут будут нюансы. Можно ли назвать ассемблер amd64 низкоуровневым, учитывая, что он вообще никак не соответствует тому, что творится внутри процессора? Там нет доступа к переименованным регистрам, нельзя прямо конфигурировать branch predictor, и так далее. Абстрактная машина, которую представляет ассемблер amd64 – это больше похоже на промежуточный код, чем на реальное управление железом.

А так, указатели ты можешь вообще в любом языке дёргать. Вот тебе указатели в Haskell, например. Прямо в стандартной библиотеке языка. C здесь вообще не является хоть сколь-нибудь особенным.

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

есть всякие рандомизации алресов и т.п.

Не в этом случае. Гарантируется postcondition, что возвращаемый указатель либо MAP_FAILED, либо равен переданному addr.

Диапазон виртуальных адресов может быть уже занят

…и для этого есть MAP_FAILED.

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

Стандарт - работает везде.

Очень неудачное определение. Хотя оно и похоже на то, что написал я, но сразу всё меняет. Претендентов на самоназвание «стандартом» несколько, они друг другу местами могут противоречить и ни один из них не работает именно строго «везде», не говоря уж о том, что у одного компилятора может меняться поведение в зависимости от флагов.

имеющая юридический вес в мире

Так в этом и причина регулярно возникающих споров: юридического веса то у них и нет (в отличие от многих современных языков). Вообще никакого. Только совещательный.

firkax ★★★★★
()

Всем физкульт Привет! …

Шо там Си, жив будет? …

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

пожертвую на киллера для тех кто такое предлагает

Шутка

Зачем человека убивать?
Купить ему остров, без права выезда и доступа в inet …

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

Где ты начитался этой херни? Если язык позволяет сделать zero runtime, значит это низкоуровневый язык.

Rust – низкоуровневый язык? Окей. А ведь ещё есть всякие eDSL на хачкелле, которые тоже на голом железе работают.

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

В стандарт C предложено внести лямбды и defer из golang

И лучше выдумать НЕ МОГ ...  
anonymous
()
Ответ на: комментарий от hateyoufeel

Т.е. ассемблер какой-то СТМ32F103 — низкоуровневый ЯП, а ассемблер amd64 — нет? Тебе не кажется, что это какая-то херня? В чем тогда смысл этого термина? Зачем он нужен?

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

Тебе не кажется, что это какая-то херня? В чем тогда смысл этого термина? Зачем он нужен?

Поздравляю! Ты понял, что в разделении языков на «уровни» нет особого смысла.

Подумай вот о чём: VHDL – это выше уровнем чем ассемблер или нет? А если язык можно напрямую в VHDL компилировать? Чуваки, которые пишут код на Common Lisp или Haskell и компилируют этот код в VHDL, а потом прошивают прямо в FPGA, они пишут на высоком уровне или на низком?

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.