LINUX.ORG.RU

Linux перейдёт на использование стандарта C11 в версии 5.18 или одной из следующих

 , ,


1

1

Во время обсуждения набора патчей, связанных с исправлением уязвимостей класса Spectre в коде для работы со связанными списками, стало ясно, что проблему удалось бы решить более изящно, если бы в ядро допускался код, использующий стандарт старше C89. Сейчас код в ядре должен соответствовать С89 (с GNU расширениями) на основе спецификации, сформированной ещё в 1989 году. Связанная со Spectre проблема была в том, что для перебора элементов списка используется макрос. Так как переменная цикла передаётся в этот макрос, то она определяется вне самого цикла и остаётся доступна после цикла. Использование более новых стандартов языка C позволит определять переменные для цикла прямо в блоке for.

В связи с этим, Линус Торвальдс предложил попробовать перейти в ядре 5.18 на стандарт C99, который был опубликован в 1999 году, на что получил встречное предложение перейти сразу на C11. При проверке сборки в GCC и Clang с новым стандартом проблем пока не возникло и, если при более тщательном тестировании ситуация не изменится, в сборочных скриптах ядра 5.18 опция --std=gnu89 будет заменена на --std=gnu11 -Wno-shift-negative-value.

В случае неудачи, переход будет отложен на один из следующих выпусков.

>>> Подробности



Проверено: xaizek ()
Последнее исправление: maxcom (всего исправлений: 5)
Ответ на: комментарий от firkax

И не регистр, а виртуальное lvalue

lvalue, это не термин ассемблера или машинных кодов. Это более высокоуровневый термин.

Сама же область видимости, в хорошем оптимизирующем компиляторе, не влияет на кодогенерацию НИКАК.

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

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

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

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

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

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

Не надо писать, ориентируясь на худший случай.

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

Зачем ты задаешь явно идиотский, демагогический вопрос? Перегрузка операторов тебе знакома? Ошибки возможны? Тебе на русский или английский алфавит тоже пруфы нужны? Классы и объекты ты в си видел? Си проще.

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

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

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

а резервирование места под него в стеке функции

Не факт. Для коротких циклов он вполне может в регистре жить всю дорогу.

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

Конкретный пример ошибки, который не имеет аналогов в С.

Вот контрпример - пожалуйста, используя std::vector я в принципе не могу получить утечку этого блока или double-free, в отличие от возни с malloc.

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

Более того, его вообще может не быть, если цикл векторизуется.

anonymous
()
Ответ на: комментарий от anonymous
void *p = malloc(size);
f(p);
free(p);

В си тут нет утечки, в плюсах - возможна. Если что, нормальные люди return в макросы не пихают, а кидать исключения - норма.

use-after-move. string_view/span. Автозахват shared_ptr в лямбду. Все это - удобная автоматизация ошибок. В си возможны аналоги, но придется писать руками, и в процессе обычно приходит осознание.

Невменяемо сложный резолвинг имен. Комплект правил почти никто не вспомнит верно. Вызваться легко может не то что ты думал. Аналогично с выводом типов. Аналогично с initializer_list: что вызывается в std::vector{1, 2} - неочевидно.

Это только сходу, из того что сам видел. Список можно продолжать бесконечно.

// Другой анон. Всё вышесказанное - не в защиту C. C must die.

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

О, еще вспомнил классику. Автогенеренный (неправильно) конструктор копирования. В сочетании с неявно делающимися копиями - мм, красота.

Только не надо про «а вы пишите без ошибок». Речь именно о новых возможностях для ошибок. И их делают, иногда даже опытные.

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

В си тут нет утечки, в плюсах - возможна.

Каким образом от того, что ты переключил язык тут появится утечка? Если ты уж в таком стиле пишешь на плюсах, то собирай с -fno-exceptions.

Но если уж говорить про C++-стиль, то это нарушение базового бана на «ручное» управление ресурсами. Поставь make_unique вместо malloc и будет счастье - и короче, и безопаснее, и гадать не надо - функция f(void*) использует указатель или его прикапывает? меняет объект или нет? можно ли вызывать из разных потоков или нет?

use-after-move. string_view/span.

это тот же самый класс ошибок, что и с управлением ресурсами в C. Только вот во-первых, они легко отлавливаются базовыми статическими анализаторами, или же moved-from object все еще валидный - (unspecife, but valid state), то есть можно вызывать методы без preconditions, например reset(), size(), clear(). У freed object нельзя.

Автозахват shared_ptr в лямбду

Вот это я не понял, наверное это больше похоже на Ява-стиль, у нас все указатели, все shared, что при тупом применении в C++ дает кольцевые ссылки. Не понимаю, как это является «новым классом» ошибок. Как это в C делается? «аккуратно подумать, где объект должен освободиться?»

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

это про ADL? на практике проблемы возникают только в generic коде, когда операторы по какой-то причине могут быть перегружены криво. Но generic programming вещь достаточно сложная и именно поэтому в STL много на первый взгляд ненужных вещей.

Да, такого класса проблем в C быть не может, просто потому что там нет generic programming, вместо того, чтобы один раз написать хорошую библиотеку контейнеров нужно каждый раз очень сильно наприягаться. Ты давно пользовался C-шным qsort?

Аналогично с initializer_list: что вызывается в std::vector{1, 2} - неочевидно.

исправлено в C++17. Тут еще и с CTAD. https://godbolt.org/z/KPETb71xa

Автогенеренный (неправильно) конструктор копирования.

все правильно генерируется, не надо просто ресурсами вручную управлять. «правило нуля» очень простое - или класс владеет единственным ресурсом, или несколькими, но через (в)рапперы. Это даже в C# есть - как правильно реализовывать IDisposable.

И какие альтернативы в C? аккуратно следить за тем, что вложенные структуры правильно проинициализированы и клонируются?

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

Вот это я не понял, наверное это больше похоже на Ява-стиль, у нас все указатели, все shared, что при тупом применении в C++ дает кольцевые ссылки. Не понимаю, как это является «новым классом» ошибок. Как это в C делается? «аккуратно подумать, где объект должен освободиться?»

Что то, брат программер, ты в попытке оправдаться совсем сову порвал. Таких ошибок в си нет вообще. И вообще, не понимаю, ну зачем грубо врать и передергивать ради «любимого» или «нелюбимого» языка. Ты не можешь рожать детей. Твоя жена - может. От этого факта ни она не становится лучше, ни ты хуже. У вас просто биологически разное предназначение. Си проще, содержит меньше ошибок, они легче ловятся анализатором (правда не все), требует очень большого внимания при написании кода. Производительность программиста ниже. Но в с++ гораздо легче нагородить ошибок которые заметят далеко не сразу. Просто потому что с++ сложнее.

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

ну зачем грубо врать и передергивать

где это я соврал? Аргументы закончились, поэтому только «врать» и «сложный» остались? И какое-то абсолютно иррелевантное замечание про рождение детей?

Си проще, содержит меньше ошибок

как может язык содержать меньше ошибок? грамматических в спецификации?

Просто потому что с++ сложнее … гораздо легче нагородить ошибок

Поинт понятен, но я с ним не согласен. Да, С++ как язык сложнее, но сложность по большей части в реализации компилятора. Ты пишешь компилятор или прикладной код? У нас есть 3 адекватных компилятора. Это в 3 раза больше, чем у многих других языков и примерно столько же, сколько и у C. Даже если говорить о портировании на другие архитектуры - действительно. гораздо легче написать компилятор С, чем C++ с нуля. Только вот никто так не делает (или я не знаю примеров):

  1. Достаточно портировать бакенд существующего компилятора (llvm или gcc), чтобы получить сразу кучу языков под свою архитектуру
  2. Можно купить фронтенд, например у EDG, который может в C транспилировать, и уже писать прикладной софт на нормальном языке.

Прикладной код на C++ гораздо экспрессивнее и есть буквально пара правил, которые очень легко применять, и благодаря которым код получается корректный. И, что самое важное, всегла есть выбор - писать на высоком уровне с исключениями и прочим, или на низком (как на C), или где-то между. Причем выбор можно делать для каждого компонента.

В C такого выбора нет.

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

Человек неудачно выразился, очевидно же имеется в виду код на С и С++. Где ты врешь мне, например, не очевидно, а передергиваешь вот здесь:

Вот это я не понял, наверное это больше похоже на Ява-стиль, у нас все указатели, все shared, что при тупом применении в C++ дает кольцевые ссылки. Не понимаю, как это является «новым классом» ошибок. Как это в C делается? «аккуратно подумать, где объект должен освободиться?»

Замечание про рождение детей абсолютно уместно - он его вполне четко пояснил. Есть разные языки для разных целей. Ты же топишь за использование мужчин, грубо говоря, и как Папы и как Мамы. Есть конечно такие люди, но детей у таких пар я не видел. Результат не очень.

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

Ты в целом всё верно говоришь, но не о том. Я показал, где в плюсах появляется пространство для ошибок, которых нет в си, или в си их совершить трудно. Эти ошибки делают в плюсах и не делают в си. Всё просто.

Вот это я не понял

Из своего опыта. Долгоживущая (или вечно-) лямбда с [=], в нее поймался локальный shared_ptr. Результат - утечка. Как на такую наткнуться в C? Про «надо не так, надо вот как» всё понятно, речь не о том.

это про ADL?

Про весь набор правил, включая ADL. Например: https://en.cppreference.com/w/cpp/language/unqualified_lookup

на практике проблемы возникают только в generic коде

Нет, конечно. Любую библиотечную функцию вызови. Если автор увлекается перегрузкой, неймспейсами, специализацией шаблонов, … - то либо молись что всю магию он продумал верно, либо положись на IDE с семантическим анализом. Благо, такие появились. При этом легкое движение в клиентском коде может переключить на другую реализацию.

все правильно генерируется, не надо просто ресурсами вручную управлять

Да вся разработка на плюсах сводится к «всё там правильно, просто соблюдайте 10500 правил». Да, соблюдаем. Но раз в год ружье стреляет.

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

И какие альтернативы в C?

Всё руками, очевидно. Нет, не считаю что это лучше, сам выбираю плюсы. Но это, как кто-то отметил выше, означает в том числе «размениваю одни баги на другие».

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

Я просто любитедь-программист.

Мне нравились синтаксические ограничения с89 стандарта, с99+, не считая изменений в стандартную библиотеку, считаю вредным заимствованием из С++ (и то, не все изменения в стандартную библиотеку обобряю, как пример - stdbool.h).

black_cat
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.