День смерти стандартной библиотеки

Автор оригинала: cor3ntin
  • Перевод
На днях в Праге комитет по стандартизации С++ провел ряд опросов по вопросу изменения ABI, и в конечном счете было решено ничего в нем не менять. Аплодисментов в зале слышно не было.
Я думаю, мы не осознавали полностью те последствия, которое повлечет за собой данное решение, и я не верю, что оно в принципе может положительно сказаться на развитии языка.



Что такое ABI


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

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

  • Добавили новое поле в уже существующий класс
  • Поменяли шаблонные параметры у класса/функции, превратили шаблонную функцию в нешаблонную или наоборот, добавили variadic template
  • Применили спецификатор inline к чему-либо
  • Добавили параметры по умолчанию в объявлении функции
  • Объявили новый виртуальный метод

И многое, многое другое, однако примеры выше — основные, что упоминаются комитетом, и те самые, благодаря которым большинство предложений в стандарт уничтожают на месте. Я опустил варианты нарушения ABI, в ходе которых ломается и исходный код программы (к примеру, удаление или изменение функций). Однако, и это не всегда верно. К примеру, удаление функции не всегда влечет за собой поломку исходного кода. std::string имеет оператор преобразования в std::string_view, от которого я бы с радостью избавился, и хоть его удаление и сломает ABI, но не приведет к значительным проблемам в исходном коде.

Почему мы должны сломать ABI


Прежде всего, есть несколько полезных изменений в реализации стандартной библиотеки, которые можно внедрить, если нарушить текущий ABI:

  • Сделать ассоциативные контейнеры (намного) быстрее
  • Ускорить работу std::regex (На данный момент быстрее запустить PHP и выполнить на нем поиск по регулярному выражению, чем использовать стандартный std::regex)
  • Некоторые изменения в std::string, std::vector, а также в разметке других контейнеров
  • Единство интерфейса классов: на данный момент некоторые их реализации намеренно не соответствуют единому интерфейсу в угоду стабильности ABI

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

  • std::scoped_lock был добавлен для того, чтобы не сломать ABI изменением lock_guard
  • int128_t не может быть стандартизирован, потому что меняет intmax_t. Однако, если бы спросили меня, я бы просто сказал, что intmax_t должен стать deprecated
  • std::unique_ptr мог бы храниться в регистре с помощью некоторых модификаций в языке, что сделало бы его zero-overhead по сравнению с обычным указателем
  • Большинство изменений для error_code были отклонены как раз из-за того, что они влекли за собой поломку ABI
  • status_code также вызывает проблемы с ABI
  • Предложение добавить фильтр в recursive_directory_iterator было отклонено, потому что сломало бы ABI
  • Предложение сделать большинство функций из библиотеки <cstring> constexpr (включая strlen) скорее всего тоже будет отклонено, ведь ломает ABI
  • Добавление поддержки UTF-8 в std::regex — поломка ABI
  • добавление поддержки в realloc и возврат размера аллоцированной памяти является поломкой ABI для полиморфных аллокаторов
  • Создание неявных виртуальных деструкторов для полиморфных типов
  • возвращаемый тип у push_back может быть изменен, если сломать текущий ABI
  • А вообще, действительно ли нам нужен и push_back, и emplace_back?
  • Улучшение std::shared_ptr также влечет за собой поломку ABI
  • [[no_unique_address]] мог бы выводиться компилятором, если бы мы не заботились о сохранении текущего ABI

И на этом список не заканчивается. Я думаю WG21 стоит стараться поддерживать актуальным список таких вот вещей. А я же буду брать на заметку каждого, кто произносит «это сломает ABI», находясь со мной в одной комнате.

Что еще мы хотим изменить?


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

  • Во время разработки модулей для C++23 мы снова столкнемся с проблемами ABI, потому что все не-экспортируемые символы должны будут оставаться в глобальной части модуля, чтобы не сломать ABI. Этот факт в принципе уничтожает весь смысл модулей как таковых
  • Существует очень много людей, которые уверены, что стоимость исключений может быть значительно снижена в тех местах, где хромает качество реализации, однако все это опять же скорее всего потребует сломать ABI
  • Дальнейшие улучшения корутин могут привести к проблемам с ABI, и их как раз можно существенно улучшить
  • Перемещение объектов требует явного оператора, опять же по причинам ABI
  • Предложения Tombstone точно приведут к проблемам с ABI

Обсуждение ABI в Праге


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

Основные факты:

  • WG21 не желает ломать ABI в 23 году
  • WG21 считает нужным сломать ABI в следующих версиях C++ (С++26 или далее)
  • WG21 потребуется время на рассмотрение предложений, которые нарушают ABI
  • WG21 не обещает вечную стабильность
  • WG21 считает важным сохранить приоритет на производительность, даже в ущерб стабильности языка

В этих заявлениях есть много важных моментов, но нет единого мнения. Комитет, как ни странно, разделился пополам.

Гадание по кофейной гуще


В какой версии C++ ждать изменений


Очевидный недостаток всех этих опросов заключается в том, что мы так и не определились, когда именно мы хотим сломать ABI.

в C++23? Нет, уже точно нет.

в C++26? Часть людей намерены голосовать за, но другая часть скорее всего проголосует за C++41 или за то время, когда они уйдут на пенсию и им не придется поддерживать свой текущий проект. Один из вопросов просто упоминал C++-какой-то; очень удобно!

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

Я не думаю, что в опросе, проведенном через три года что-то изменится. Это как глобальное потепление: все согласны, что нужно когда-нибудь заняться этой проблемой. А давайте тогда запретим дизельное топливо в 2070?

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

О предложениях, которые нарушают ABI


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

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

Производительность важнее стабильности ABI


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

Мне кажется, комитет одновременно хочет усидеть сразу на двух стульях. А это невозможно:
Bryce Adelstein Lelbach @blebach
— Производительность
— Стабильность ABI
— Возможность что-либо менять

Выберите два варианта из предложенных.

стабильность языка и ABI в конечно счете сталкиваются друг с другом, заставляя нас задаться таким фундаментальным вопросом — Чем является C++ и чем является его стандартная библиотека?

Обычно в таком случае вспоминают термины «производительность», "zero-cost абстракции", "do not pay for what you do not use". А стабильность ABI стоит поперек всему этому.

Далеко идущие последствия


image

Я глубоко убежден, что решение не ломать ABI в 23-м году — это самая большая ошибка, которую когда-либо делал комитет. И я знаю, что некоторые люди верят в обратное. Но вот что скорее всего случится в скором времени:

Кошмар обучения


Давайте будем честны. Все программы, которые полагаются на ABI, скорее всего где-то нарушают принципы ODR или используют несовместимые флаги, которые по счастливому стечению обстоятельств все еще работают.

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

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

Отказываясь нарушать ABI, комитет открыто заявляет, что будет поддерживать плохо написанные программы на протяжении всего их существования. Даже если вы не будете линковаться с библиотеками, полученными через apt-install (которые на самом деле предназначены для системы), то другие люди будут, ведь комитет дал им на это свое благословение.

Это огромный шаг назад. Как мы можем учить других хорошим практикам языка, если для этого у нас нет никакого стимула?

Потеря интереса к стандартной библиотеке


Предполагаемая потеря в производительности библиотеки из-за нашего нежелания нарушать ABI оценивается в 5-10%. Это число будет только расти со временем. Давайте посмотрим на примерах:

  • Если вы — большая компания, то можете купить себе новый датацентр или платить команде программистов, которые бы поддерживали свою собственную библиотеку
  • Если вы разработчик встраиваемых систем, то эти 5% могут стать гранью между работающим продуктом и необходимостью купить более дорогой и мощный чип, а он может стоить миллионы
  • Если вы игровая компания, то эти 5-10% могут решить, станет ли ваша игра крутой или будет ли ваших пользователей тошнить от нее в VR-шлеме
  • Если вы трейдинговая компания, то скорее всего для вас эти проценты — успешно проведенная или проваленная транзакция

Я думаю, тут волей-неволей встает вопрос между: «Мне однозначно стоит использовать C++ и его стандартную библиотеку!» и «Быть может, мне не стоит использовать стандартную библиотеку? Или может, мне не стоит использовать C++ в принципе? Возможно, .NET, julia или Rust будут лучшим решением?». Конечно, есть много факторов, которые влияют на ответ, но мы видим, что происходит в последнее время.

Множество разработчиков игр относятся крайне скептически к стандартной библиотеке. Они скорее разработают свою альтернативу, к примеру EASTL, чем воспользуются STL. У Facebook есть folly, у Google — abseil и так далее.

Это как снежный ком. Если люди не используют стандартную библиотеку, у них нет и интереса ее улучшать. Производительность — это тот ключевой фактор, который удерживает библиотеку на плаву. Без гарантии производительности намного меньше усилий будет приложено в ее развитие.
>> Jonathan Müller @foonathan
В чем смысл использовать контейнеры из стандартной библиотеки, если они не предоставляют лучшую производительность?

Titus Winters @TitusWinters
Возможно, потому что они распространены и легкодоступны? (эти два факта не значат одно и то же).
Голосовать за сохранение ABI это все равно что сказать, что стандартная библиотека должна стремиться быть МакДональдсом — он также есть повсюду, он стабильный и технически решает поставленные задачи.

Как комитету рассматривать предложения, ломающие ABI?


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

Добавление новых имен


image

Это первое и очевидное решение. Если мы не можем поменять std::unordered_map, может нам просто добавить std::fast_map? Есть несколько причин, почему так делать плохо. Добавление типов в стандартную библиотеку обходится дорого как с точки зрения расходов на поддержку, так и с точки зрения образования. После введения нового класса неизбежно появятся тысячи статей, в которых объясняется, какой контейнер стоит использовать. К примеру, мне следует использовать std::scoped_lock или std::lock_guard? А я понятия не имею! Мне нужно каждый раз гуглить. Также есть проблема, что хорошие имена рано или поздно заканчиваются. Еще мы получаем некоторый оверхед во время выполнения программы, так как все контейнеры должны постоянно преобразовываться друг в друга, огромное число перегрузок конвертации у класса становится трудно контролировать и т.п.

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

Но ведь мы могли принять это предложение в стандарт!


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

Мне, как циничному человеку, немного трудно в это поверить. Дело в том, что раньше таких предложений не было, да и сценарии, в которых они могут быть применены весьма ограничены. ABI Review Group (ARG) могла бы помочь в этом вопросе, но они скорее всего снова порекомендуют придумать другое имя для класса / функции.

Частичное нарушение ABI


Основная идея заключается в том, чтобы не ломать весь ABI, а только изменить его для определенного класса или функции. Проблема такого подхода заключается в том, что вместо ошибки на этапе линковки, мы будем видеть проблему уже во время запуска программы, и это будет неприятно нас удивлять. Комитет уже попробовал такой подход в С++11, когда поменял разметку std::string. Ничего хорошего из этого не вышло. Все было настолько плохо, что этот факт до сих пор используется как аргумент в пользу сохранения текущего ABI.

Еще один уровень индирекции


Решением части проблем с ABI было бы возможность обращаться к данным класса через указатель, тогда бы и разметкой класса был всего лишь этот указатель. Идея очень близка к идиоме PIMPL, которая активно используется в Qt из-за его ABI. Да, это бы решило проблему с членами классов, но что делать с виртуальными методами?

Рассматривая проблему с более критической точки зрения, мы говорим о добавлении еще одного уровня косвенности (индирект по указателю) и дополнительной аллокации памяти в куче для всего того, что заключено в рамках ABI. В STL, по факту, все заключено в этих рамках, потому что это набор обобщенных классов.

В итоге цена такого подхода будет огромной.

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

Иронично, однако, но чтобы превратить библиотечные типы в PIPML-типы, нам нужно… сломать ABI.

Пересобирать весь код каждые три года


Просто мои мысли вслух.

Все текущие предложения в стандарт должны быть уничтожены


Парадоксально, но C++ никогда не был настолько живым, как сейчас. В Праге 250 человек работали над множеством вещей для него, среди которых:

  • Numerics
  • Линейная алгебра
  • Аудио
  • Юникод
  • Асинхронный I/O
  • 2D и 3D Графика
  • Множество других фич

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

А потом, над горизонтом нависает такой ужас, как networking. Очень и очень безответственно пытаться стандартизировать что-либо, что может повлечь за собой проблемы безопасности, и при этом не иметь возможности это впоследствии изменить (вспоминаем про ABI).

Поскольку C++ решили сделать стабильным, все эти предложения должны быть уничтожены и сожжены. Я бы не хотел, чтобы их уничтожали, но это необходимо сделать.

Но этого все равно не сделают.

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

Но конечно, мы совершим еще много, много ошибок.

>> Ólafur Waage @olafurw
(Это очень хорошо сработало в прошлый раз, поэтому я попробую снова)

День добрый, твиттер программистов!

Я собираюсь выступать перед амбициозными молодыми людьми через пару недель. Какой по вашему мнению самый важный совет, который можно дать разработчику ПО (к примеру: паттерны, архитектура, алгоритмы)?

Hyrum Wright @hyrumwright
Рано или поздно любое решение, принятое во время разработки, придется изменить. Предусматривайте возможность изменения в вашей экосистеме — как в ваших инструментах, так и в самом процессе разработки.

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

Время идет, но стандартная библиотека стоит на месте. Ранее сделанные трейд-оффы постепенно начинают нам мешать, а в последствие становятся настоящими «бутылочными горлышками» в существующем коде.

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

C++ все еще будет на плаву в ближайшие 40 лет. Если мы не сможем осознать необходимость менять его непредсказуемым образом в любое время, то единственным верным ходом останется только не играть в эту игру в принципе.

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

Ваше предложение в стандарт будет уничтожено, мое точно также будет уничтожено.

Может ли комитет в принципе сломать ABI?


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

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

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

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

Стоит ли ломать ABI?

  • 83,2%Да, как можно скорее277
  • 6,6%Да, но не в ближайшие пять лет22
  • 10,2%Нет, нужно оставить все как есть34
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 92

    +1
    > Комитет уже попробовал такой подход в С++11, когда поменял разметку std::string.
    > Ничего хорошего из этого не вышло.

    а можно подробности?
      +1
      инфы действительно немного, но как минимум по этому поводу есть небольшая статья у gcc: gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
      основной идеей было начиная с C++11 запретить реализовывать std::string как copy-on-write строку, а также стандартизировать SSO(small string optimization), что конечно же ломало ABI строки.
        0
        все равно не пойму — есть проблемы с точки зрения разработчика, использующего std библиотеку при смене ABI?
          +2
          если вы используете STL (то есть по сути подключаете только заголовки), то никаких проблем нет, так как программа каждый раз по сути собирается из исходников, компилятор просто инстанцирует шаблоны. Проблемы начинаются тогда, когда ваше приложение собирается в виде liи/dll/so файла и наружу торчит что-либо из стандартной библиотеки.
            +2
            Веселье может начаться, если у вас в проекте разные части (библиотеки) собираются с разными стандартами плюсов, например, или с разными опциями _GLIBCXX_USE_CXX11_ABI.
          0
          Там были проблемы в link-time, но проблем в runtime я чтото не упомню
          +2
          хотите хоронить с++ — тяните билетик, запасайтесь провиантом и вставайте в очередь.

          Часть изменений, которые назвал автор статьи, влекут поломку не только ABI, но и API (смешались в кучу люди, кони). Поломка первого почти болезненна, переход занимает всего лишь лет 5. Поломка второго неизбежно фрагментирует плюсы так же, как когда-то питон, когда язык по сути разделился на два параллельно существующих по сей день.

          Если не подготовить способы внедрять изменения безболезненно, сообщество столкнется с тривиальнейшей проблемой: потом придется менять еще раз. И не единожды. А переписывать код до бесконечности любят не только лишь не все.
            +6
            И тем не менее, Python 3 продолжает развиваться и преобладает по сравнению со 2-ым (поддержка которого к слову уже закончилась вместе с началом 2020 года). По сути сейчас все оставляют как есть в угоду компания со своими древнейшими жирными монолитами кода, а из-за этого страдают новые проекты. Хотя по-хорошему в таком случае нужно просто оставаться на старой версии языка/компилятора.
              +7
              И тем не менее, Python 3 продолжает развиваться и преобладает по сравнению со 2-ым
              он не так давно начал преобладать
              поддержка которого к слову уже закончилась вместе с началом 2020 года
              да да, а для работающих на втором питоне сервисов поменялся разве что таймстамп
              По сути сейчас все оставляют как есть в угоду компания со своими древнейшими жирными монолитами кода, а из-за этого страдают новые проекты
              не так просто. Есть у вас какой-нибудь проект на линуксах, который использует 100500 библиотек. Вот чтобы перевести его на новый стандарт с поломкой ABI нужно не только пересобрать ваш проект, но и чтобы все мейнтейнеры пересобрали и выложили эти 100500 библиотек. И если хоть одна из этих либ будет проприетарной, вам придется ждать пока эта контора обновит библиотеку. Если вообще когда-либо обновит.
                +1
                Если есть проект который использует 100500 библиотек, и не может быть серьезно изменен (отказаться от несовместимых библиотек), то что мешает оставаться на старых плюсах? И по сей день можно непринужденно использовать С++11, чем, собственно, многие крупные компании и занимаются.
                  0
                  И заодно заставить вендоров всех этих 100500 библиотек тоже не использовать при их сборке ничего выше C++11?
                    +1

                    Зачем? Можно оставить старые версии закрытых библиотек.

                      0
                      Даже если в них есть критичные баги или уязвимости?
                        +1

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


                        Да и фиксы багов и уязвимостей можно и бэкпортить.

                          0
                          В закрытых библиотеках что-то бэкпортить самому довольно проблематично.
                            0

                            Так пусть вендор бэкпортит. Юзать новые версии C++ в новых версиях библиотек это ему не помешает.

                              0
                              Так пусть вендор бэкпортит.
                              М-м-м.
                                0

                                Не понял, поэтому на всякий случай не соглашусь.

                                  0
                                  Это была попытка выразить небольшое сомнение :)
                                    +1

                                    По моему опыту вендоры либо давно забили на библиотеку (и вопрос решился сам собой), либо активно её поддерживают и очень хорошо отвечают на запросы, либо библиотеки имеют C API, а зависимостей от lib[std]c++ не имеют.

                      0
                      Не, либо вендоры используют новую ABI, и проблем нет, либо вендоры не хотят обновлять либу, и тогда все вместе старый ABI.
                        +1
                        Ну вот смотрите. Предположим, в очередном новом стандарте было изменено внутреннее представление/разметка какого-то контейнера. И вот основной код и большая часть библиотек у вас используют старый ABI, но некоторая часть использует новый, причем эта часть, нопремер, распространяется вендором без исходников, binary only. И вот из кода, собранного в старом стандарте, нужно передать такой контейнер в код, собранный в новом стандарте (ну, или наоборот), чтобы он там с ним поработал как-то. Что делать будете? А если таких вендоров много, и часть распространяет свои собранные либы со старым ABI, а часть — с новым?

                        P.S. Вот здесь собственно проблема и все варианты ее решения (которые «оба хуже») уже обозначены.
              0
              Краткое содержание статьи: «Stable ABI Nonsense». :)
                +6

                Сначала добавление префикса "co_" без какой бы то ни было веской причины, теперь отказ от такой очевидной вещи, как возможность смены ABI в мажорном релизе и снова без веских на то причин… Всё это как минимум не выглядит разумным.


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

                К слову, Qt ломает ABI каждый мажорный релиз. Никто от этого не умер.

                  +2
                  Qt и в пределах мажорного релиза (5.3_WinXpCompatible-to-5.4_Win7+) ломали, вроде умерли не только лишь все. Был лишний повод обязать клиентов обновить Windows, и то где-то в районе версии 5.13, да и то из-за определенных проблем MinGW до 7й версии. Технически кому надо — соберет и под 5.3.

                  А так, от stdlib для бОльшего количества разработчиков не хватает на самом деле самых простых вещей — networking, простой в использовании async, тот же regex удобный, для библиотекарей — наверное комфортные концепты для templates, может даже математики векторной/матричной завернуть тоже, комфортный multithreading/multiprocessing… и что-бы все было гарантировано кросс-платформенное и из коробки.

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

                    Qt и API ломает, иногда даже в рамках минорных релизов. При переходе на 5.14 сломался кое-какой код из-за ЕМНИП новых перегрузок конструкторов QList.

                    +8
                    Немного нечестно с моей стороны писать тут, потому что cor3ntin не знает русского, но:
                    * «Сделать ассоциативные контейнеры (намного) быстрее» — нет, не «намного»! Предложенные изменения для стандартных контейнеров ломают в первую очередь API, потому что они убирают методы для работы с нодами и итерации по корзинкам.
                    * «Ускорить работу std::regex (На данный момент быстрее запустить PHP и выполнить на нем поиск по регулярному выражению, чем использовать стандартный std::regex)» — основное что тормозит в std::regex, это локали. Убрать локали — это изменение API а не ABI.
                    * «Некоторые изменения в std::string, std::vector, а также в разметке других контейнеров» — скорее всего речь идёт про добавление SSO в vector, а это прежде всего ломает его гарантии по инвалидации итераторов. То есть это опять слом API а не ABI.
                    * «Единство интерфейса классов: на данный момент некоторые их реализации намеренно не соответствуют единому интерфейсу в угоду стабильности ABI» — да, это осознанное решение одного единственного вендора. И что бы не решил в этом месте комитет — это личное дело вендора, когда именно ломать ABI. Планы комитета стандартизации, которые пойдут в разрез с планами вендора, будут проигнорированы. Ибо от ABI зависит бизнес вендора и его финансовое благосостояние.
                    * «Предложение добавить фильтр в recursive_directory_iterator было отклонено, потому что сломало бы ABI» — оно было отклонено, потому что оно дурное. Автор предложения неправильно написал бенчмарк, что сводило полезность и достоверность его предложения на 0.
                    * «Предложение сделать большинство функций из библиотеки constexpr (включая strlen) скорее всего тоже будет отклонено, ведь ломает ABI» — это можно реализовать без слома ABI. Комитет отправил нас исследовать этот вопрос, мы поисследовали, всё ОК.

                    Ну и в целом: голосование решило что форсить слом ABI не будем, потому что вендоры могут не поддержать; голосование сказало что при наличии достойной идеи ломать ABI — это ОК. Трагедии особой не вижу. Единственная проблема — голосование получилось нейтральным, из-за этого противники и сторонники слома одинаково недовольны.
                      0
                      да, это осознанное решение одного единственного вендора.

                      А можете намекнуть, что это за вендор?
                        +2
                        GCC. Все коммерческие продукты, поставляемые в бинарном виде для Linux, надеются на неизменность ABI, благодаря чему они могут не пересобирать свой продукт под каждый новый дистрибутив.

                        Разумеется можно сломать ABI, но тогда коммерческие продукты вынуждены будут либо
                        * собирать только под новый ABI, и забросить поддержку старых платформ
                        * собирать только под старый ABI (потому что он везде поддерживается), и тогда новый ABI немного теряет смысл.
                        * собирать под новый и старый ABI, что они навряд ли захотят делать
                          0
                          а можно как-то в одной libstdc++ смешать символы с двумя разными ABI, например?
                            0

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

                              0
                              ну это дает полную обратную совместимость. А новый код можно порекомендовать собирать со static-libstdc++
                                +1

                                Не совсем. Библиотека использует старые std::string, а приложение — новые. Ладно, мы разработчики приложения и можем сказать использовать старые std::string тоже, но тут появляется вторая библиотека, на которую мы повлиять не можем, а она использует новые std::string.

                            0

                            А можете пояснить вот такой момент: для той же visual studio статическую библиотеку приходится собирать под 4 версии стандартной библиотеки ((дебаг + релиз) * (однопоточная + многопоточная)). И для каждой версии компилятора (2013, 2015 и т.д.) свой набор ещё конечно же.
                            Я верно понимаю что GCC сохраняет совместимость на том уровне, что собранное статическое чудо условно версией 4.0 будет работать без проблем с версией 5.0, с другой соответственно реализацией стандартной библиотеки, другими "фишками" компилятора и т.п.?
                            Или какие-то ограничения есть?

                              +3
                              И для каждой версии компилятора (2013, 2015 и т.д.) свой набор ещё конечно же.

                              Студия с 15 версии сохраняет своё ABI, библиотеки скомпилированные в 2015 версии без проблем линкуются в 2017 и 2019
                                0
                                так уж и без проблем. Вот например в 15.7 были проблемы. А в какой-то (то ли 15.4 то ли 15.6) я ловил вот такую бинарную несовместимость с атомиками.
                                  +1
                                  Ну это по большей части баги, а так в основном проблем практически нет.
                                    +2
                                    считайте что причина менять ABI c++ — поправить баги в проектировании языка и/или стдлибы.
                              +3

                              Всё-таки неясно, в чем отличие от обычной ситуации с библиотеками: например, в debian часто в рамках одного дистрибутива бывает несколько версий одной библиотеки. Понятно, что если слинковаться с несколькими одновременно и передавать объекты, то будут проблемы.
                              Почему здесь, если поступить также и сделать две stdc++, то ожидаются непреодолимые трудности?

                                0
                                На самом деле, здесь есть другая проблема — если коммерческий продукт активно развивается и хочет идти в ногу со временем, то так или иначе он будет использовать новые возможности языка и библиотеки. И в этом случае он не будет работать на старых дистрибутивах со старыми версиями стандартной библиотеки даже при неизменном ABI. А обновлять дистрибутив на стабильно работающем боевом сервере никто не желает. Поэтому остается единственно приемлемый вариант «все свое ношу с собой». Конечно при неизменном ABI можно не таскать остальные библиотеки, но это только в том случае, если они остаются старых версий. А тут уже оказывается, что далеко не все мэйнтэйнеры так же пекутся о совместимости ABI в новых версиях библиотек. Да еще, если оставаться на старых библиотеках, порой патчи безопасности на них нужно накладывать, т.е. опять же делать свою сборку и тащить с собой. В общем — «куда ни кинь — всюду клин». Так что неизменность ABI не сильно спасает коммерческих вендоров.
                                  0
                                  А что мешает линковаться статически со стандартной библиотекой?
                                    0
                                    То что другие библиотеки могут линковаться динамически
                                      0
                                      Обычно их можно пересобрать.
                                        0
                                        А что делать с теми которые нельзя пересобрать? У меня таких вот очень много.
                                +1

                                Добавлю к списку:


                                • "Создание неявных виртуальных деструкторов для полиморфных типов"
                                  Плохая идея сама по себе, даже если бы не требовала слома ABI.
                                • "возвращаемый тип у push_back может быть изменен, если сломать текущий ABI"
                                  Можно поменять и не ломая ABI, как это сделали в C++20 для std::list::remove.
                                • "А вообще, действительно ли нам нужен и push_back, и emplace_back?"
                                  Объединить их можно было бы, но тут надо опять говорить об API а не ABI.
                                  +2

                                  Я, кстати, не понимаю: ABI уже сломали в C++17 (noexcept стал частью типа, и функции, принимающие указатели на noexcept-функции, манглятся по-разному).


                                  GCC вроде как сломает ABI в GCC 10 (что-то там про глобалы, я не исследовал подробно).


                                  Так о чем разговор?

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

                                    PS: у нас на проекте своя реализация стандартной библиотеки (и не только ее. не спрашивайте), так что я на это все смотрю с попкорном. Лично я бы начал с того, что добавил способ спросить функцию в либе (хоть статической хоть динамической) — с какой ABI она умеет работать. А потом уже там все улучшал.
                                  +1
                                  Как по мне надуманная проблема, можно переписать заново STL и выложить его как STL V2, что бы новые проекты уже писались на нем.
                                    +1
                                    А что там с эпохами (те, что из раста)? Они вроде могут решить какие-то проблемы.

                                    А, ну и C++, который мы потеряли. Все как обычно.
                                      +1

                                      А кто первый предложил перейти на "std42::", т.е. тупо использовать разные неймспейсы для новых ABI?

                                        0

                                        Эквивалентно использованию разных имён с теми же проблемами.

                                          0

                                          Пардон, но как могут быть те же проблемы с новыми именами. Кто мешает ломать совместимость каждые 10 лет в новом std:: ?

                                            0
                                            Проблема в сложности и проблема в обучении остаются точно такие же. Ждите статей и вопросов на собеседовании из разряда: «когда лучше использовать std31::unordered_map, а когда std42::unordered_map»?
                                              0

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


                                              Как мне кажется, при наличии std11::, std14::, std17:: и std20:: обсуждаемой проблемы ABI просто не было-бы. Но возможно я тупо не в курсе какой-то общеизвестной причины? antoshkka?

                                                +1
                                                Зато была бы другая — необходимость постоянно добавлять всякие перегрузки для новых stdXX, даже если у тебя все собирается из исходников одним и тем же компилятором, конвертировать эти stdXX туда-сюда (использую в своём коде std20, хочу использовать такую-то библиотеку, а у неё все с std11, все оборачиваем в какие-нибудь std20tostd11, даже если я её из исходников собираю). ИМХО тоже по-своему куча геморроя.
                                                  0

                                                  И?


                                                  Рано или поздно придется что-то менять с нарушением совместимости.
                                                  При этом я бы предпочел явно видеть все подобные изменения и иметь возможность совмещать старый и новый код.


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

                                                    +1

                                                    Лично мне больше нравится вариант "хочешь новую клёвую структуру данных — обзови её по-другому". Суть та же, но выглядит не настолько радикально.

                                                      0
                                                      хочешь новую клёвую структуру данных — обзови её по-другому
                                                      конвертировать эти stdXX туда-сюда
                                                        0
                                                        Ну, с другой стороны, если в каком-нибудь std::string ничего не поменялось, то он так и будет везде std::string, а не std11::string, std14::string, std17::string, std20::string, между которыми нужно будет постоянно конвертировать туда-сюда, хотя бы даже «для вида». Все-таки проще как-то.
                                                          0

                                                          То есть, я ещё и должен помнить, какие типы в каких стандартах работают друг с другом без конвертации, а какие — нет?


                                                          У меня такое чувство, что C++-новичков кому-то стало слишком много, и кто-то стал опасаться за job security.

                                                            0
                                                            Я про вариант «хочешь новую клёвую структуру данных — обзови её по-другому». Я так понял, что возражение Antervis'а состояло в том, что в этом случае тоже придется что-то конвертировать в эту «новую клевую структуру», то есть если функция принимает std::super_duper_fast_map, то чтобы передать в нее обычный std::map, придется сделать конверсию. Мое возражение на это возражение состоит в том, что это нужно будет делать лишь иногда, в то время как в случае разных неймспейсов типа stdXX этим нужно будет заниматься постоянно, в коде будет куча мусора на эту тему.
                                                              0

                                                              А, ё-моё, тогда я с вами согласен, конечно!

                                                  0

                                                  Кроме этого вам нужно как минимум линейное, как максимум квадратичное число функций (неявной?) конвертации из одного типа в другой, потому что всякие там std::string, std::map и прочие — это словарные типы, которые вылезают


                                                  Плюс, конвертация — это лишние затраты, и если как-то можно без них, то хотелось бы без них.

                                          0
                                          Добавьте пожалуйста пример, как например, улучшается unordered_map и не ломая ABI приложение не собирается / не работает.
                                            0

                                            Все никак не могу понять: если сломать ABI, то какой смысл оставаться на С++?


                                            Буквально на днях (в рамках "олимпиады" посвященной переписыванию wc) в очередной раз стало понятно что компиляторы разных языков выдают примерно одинаково работающий бинарь.


                                            P.S. Я не против плюсов и своей профессиональной деятельности использую 2 языка: С++17, Python27.

                                              +1

                                              Ну да, появление LLVM дало быстрые компиляторы очень многим языкам, и сейчас наверное уже не обязательно учить плюсы, чтобы писать довольно быстрые программы. С другой стороны, зачем тем уже кто знает С++ куда-то уходить? Просто ради того чтобы уходить?

                                                0

                                                Ради новых концепций, которые в плюсах не заложены (при этом иногда реализованы, но через костыли).

                                                  –1

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

                                                    +1

                                                    Ну вот, к примеру, сопрограммы "подвозили" в язык 8 лет. Те, кто ушёл в другие языки — давно уже успели эти другие языки освоить, а то и забыть.

                                                      0
                                                      А вам принципиально, чтобы эта штука была именно в языке? Мне, честно говоря, не особо, есть в бусте — и хорошо.

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

                                                      Я уже пару лет активно пишу на Питоне (хотя и нерегулярно, да и в основном всякую мелочь), но всё равно постоянно ныряю в документацию и в целом чувствую себя гораздо менее комфортно, чем в C++.
                                                        0

                                                        Те "сопрограммы", которые в бусте, слишком прожорливы в плане памяти и переключаются не так быстро.

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

                                                            Проблемы у зелёных потоков общие для всех языков: чтобы они не были прожорливы по памяти, им нужен сегментированный стек. А сегментированный стек автоматически означает неполную совместимость с другими языками по ABI.


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

                                                0
                                                Это уж каждый сам для себя решает. Один из главных плюсов C++ лично для меня заключается в наличии огромного количества хороших библиотек на все случаи жизни, которые можно использовать напрямую, без придумывания, как бы это обернуть в какие-нибудь костыли в рамках C ABI для FFI (P.S. я о библиотеках с открытыми исходниками, для применения которых стабильность C++ ABI сама по себе не принципиальна потому, что их всегда можно пересобрать «под себя»). Новые концепции — это, конечно, хорошо, но это не есть самоцель с моей точки зрения, особенно если учесть, что особых проблем с концепциями в C++ тоже нет, он вполне себе мультипарадигмальный, и продолжает развиваться. Но, повторюсь, каждый для себя решает сам. Спорить на эту тему мне лень :)
                                                  +1

                                                  Хочу хорошую библиотеку для parser combinator'ов с хорошими сообщениями об ошибках и для программиста, и для пользователя (так что boost.spirit в пролёте).


                                                  Есть что-нибудь типа такого?


                                                  А какую библиотеку посоветуете для рисования графиков с миллионом-другим точек? Не на экране, на экране не надо, а в файл.


                                                  И это к вам ещё data scientist'ы не пришли из питона с R.

                                                  +1
                                                  Буквально на днях (в рамках "олимпиады" посвященной переписыванию wc) в очередной раз стало понятно что компиляторы разных языков выдают примерно одинаково работающий бинарь.

                                                  Это если повезёт. Если везёт, то я выдаю статью о том, как на разных языках получается код, сходный (или быстрее) по производительности с С или плюсами. Если не везёт, то, ну, статьи нет.


                                                  Тут, короче, очень мощный такой selection bias.

                                                  0
                                                  А вообще, действительно ли нам нужен и push_back, и emplace_back?

                                                  Хм… А если конструктор приватный, как элемент в коллекцию с помощью emplace_back засунуть ?

                                                    0
                                                    Для этого и существует версионность стандартов. Хочешь использовать новый стандарт — смирись с его нововведениями. Если по каким-то причинам (например из-за зависимостей) нет возможности перйти на новую версию стандарта, придётся использовать старый.
                                                      0
                                                      Я проголосовал за немедленную радикальную смену ABI. Мотивация: это так встряхнет C++, что он либо возродиться жар-птицей, либо уйдет на задворки. Как-то так...)))
                                                        +1
                                                        «Веесь миир насилья мы разрушим до основанья, а затем», пом-пом :)
                                                        –2
                                                        Понятно.
                                                        Будущее за Rust
                                                          +1
                                                          Мне в этом плане нравится комментарий к какой-то там статье очередного адепта раста: «Nice article, but have you considered writing it in Rust instead of html?» :)
                                                            0
                                                            То есть вы думаете rust'а эта проблема никогда не коснётся?
                                                              +2

                                                              Неизбежно коснётся, но будет шанс дойти до более существенных граблей.

                                                                0
                                                                но будет шанс дойти до более существенных граблей.

                                                                А на чём основана ваша уверенность в этом?

                                                                0

                                                                Не коснётся, потому (стабильного) ABI нет ¯_(ツ)_/¯

                                                                –1
                                                                Понятно. Будущее за Rust
                                                                Сорвали с языка )) Если идет переписывание ABI, то почему бы не создать новый С+++ без обратной совместимости и без ошибок прошлого.
                                                                  +2

                                                                  На моей памяти "убийц C++" уже много понасоздавали, "без обратной совместимости и ошибок прошлого". Но что-то у них с "убийством" не заладилось — есть мнение, что не в последнюю очередь из-за наплевательского отношения к "обратной совместимости", не позволяющей полноценно использовать огромную массу уже наработанного качественного кода, а также неизбежным привнесением новых граблей в процессе выполнения этапа "мы наш, мы новый мир построим". Так что поживём-увидим.

                                                                    –2
                                                                    Сишные библиотеки можно использовать

                                                                    Можно писать «небезопасные» секции с прямой работой с памятью и другими плюшками.
                                                                      0
                                                                      Да, я в курсе. Но, чтобы использовать, к примеру, тот же Qt, нужно сначала написать для него сложную обертку, которая низводит всю мощь его C++ интерфейса к ограниченному функционалу «сишной библиотеки», вполне вероятно, наделать при этом ошибок (чем больше оберток, и чем они сложнее, тем больше потенциальных ошибок). В общем, drawbacks имеются, и они значительные.
                                                                      +2
                                                                      На моей памяти «убийц C++» уже много понасоздавали...
                                                                      Это не значит, что у любого следующего не получится.
                                                                  –1
                                                                  Или может, мне не стоит использовать C++ в принципе?

                                                                  Сам факт существования множества библиотек (например части того же Qt), частично или полностью заменяющих стандартную, вопиет о недостатках и недоделках стандартной библиотеки.

                                                                  Поэтому да, ломать ABI (и пожалуй API тоже, но с умом). С ABI, пожалуй, всё ясно — открытые исходники просто пересобираются. С закрытыми всё относительно плохо, но если выбирать, либо развитие, либо смерть, то выбор очевиден. Нет, конечно, полностью C++ не умрёт, как не умер FORTRAN, но стагнация и потеря популярности неизбежна. Важно только при изменении ABI сделать следующее такое изменение (а оно тоже неизбежно), менее болезненным.

                                                                  Другое дело, как влияют на принятие решений комитетом те, кто заинтересован в заморозке ABI. Ведь понятно, что множество корпораций и фирм готовы принести C++ в жертву своим сегодняшним прибылям и выгодам. И их сегодняшние сиюминутные выгоды могут перевесить потери вызванные стагнацией языка. Но это лишь говорит о том, что если не поменять ABI сегодня, завтра это будет сделать ещё сложнее (== невозможно).

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

                                                                  Самое читаемое