Standardbibliothek zum Todestag

Neulich in Prag führte das C ++ - Standardisierungskomitee eine Reihe von Umfragen zum Thema Änderung des ABI durch, und letztendlich wurde beschlossen, nichts daran zu ändern. Es gab keinen Applaus in der Halle.
Ich denke, wir haben die Konsequenzen dieser Entscheidung nicht vollständig erkannt, und ich glaube nicht, dass sie die Entwicklung der Sprache im Prinzip positiv beeinflussen kann.



Was ist ABI?


ABI - Eine Reihe von Konventionen, die definieren, wie Ihr Programm in binärer Form dargestellt wird, wie Namen darin deklariert werden, Klassenmarkierungen definiert werden und Konventionen für Funktionsaufrufe definiert werden. Tatsächlich ist dies eine Art Binärprotokoll, aber es ist nicht versioniert.
Um Sie in der Terminologie nicht zu verwirren, schauen wir uns Beispiele an, was die ABI-Änderung und ihre Aufteilung innerhalb des Programms mit sich bringt:

Sie können das exportierte Symbol in der neuen Version Ihrer kompilierten Bibliothek nicht verwenden, wenn Sie eine der folgenden Aktionen ausgeführt haben:

  • Einer vorhandenen Klasse wurde ein neues Feld hinzugefügt
  • Die Vorlagenparameter der Klasse / Funktion wurden geändert, die Vorlagenfunktion in eine Nicht-Vorlage umgewandelt oder umgekehrt eine variable Vorlage hinzugefügt
  • Wenden Sie den Inline- Bezeichner auf etwas an
  • Standardparameter in Funktionsdeklaration hinzugefügt
  • Neue virtuelle Methode angekündigt

Und vieles mehr, aber die obigen Beispiele sind die wichtigsten, die vom Ausschuss genannt werden, und genau die, dank derer die meisten Vorschläge in der Norm sofort vernichtet werden. Ich habe die Optionen für die Verletzung des ABI weggelassen, bei denen auch der Quellcode des Programms unterbrochen wird (z. B. Löschen oder Ändern von Funktionen). Dies ist jedoch nicht immer der Fall. Zum Beispiel bedeutet das Löschen einer Funktion nicht immer, dass der Quellcode beschädigt wird. std::stringEs hat einen Konvertierungsoperator std::string_view, den ich gerne loswerden würde, und obwohl das Löschen den ABI beschädigt, führt dies nicht zu signifikanten Problemen im Quellcode.

Warum sollten wir ABI brechen


Zunächst gibt es einige nützliche Änderungen in der Implementierung der Standardbibliothek, die Sie implementieren können, wenn Sie den aktuellen ABI brechen:

  • Machen Sie assoziative Container (viel) schneller
  • Beschleunigen Sie Ihre Arbeit std::regex(Im Moment ist es schneller, PHP auszuführen und mit einem regulären Ausdruck danach zu suchen als mit dem Standardausdruck. std::regex)
  • Einige Änderungen in std::string, std::vectorsowie im Layout von anderen Behältnissen
  • Einheit der Klassenschnittstelle: Im Moment entsprechen einige ihrer Implementierungen aus Gründen der ABI-Stabilität absichtlich nicht einer einzigen Schnittstelle

Noch wichtiger ist, dass das Design der Bibliothek geändert werden kann, ohne dass das ABI-Sicherheitsproblem auftritt. Hier ist eine unvollständige Liste von allem, was aus dem oben genannten Grund derzeit nicht machbar ist:

  • std::scoped_lock wurde hinzugefügt, um die abi-Änderung nicht zu brechen 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
  • Das Hinzufügen von Unterstützung zum reallocZurückgeben und Zurückgeben der Größe des zugewiesenen Speichers ist eine ABI-Aufschlüsselung für polymorphe Allokatoren
  • Implizite virtuelle Destruktoren für polymorphe Typen erstellen
  • Der Rückgabetyp y push_backkann geändert werden, wenn der aktuelle ABI fehlerhaft ist
  • Brauchen wir im Allgemeinen wirklich und push_backund emplace_back?
  • std::shared_ptr verursacht auch einen ABI-Ausfall
  • [[no_unique_address]] könnte vom Compiler ausgegeben werden, wenn wir den aktuellen ABI nicht speichern möchten

Und die Liste endet nicht dort. Ich denke, WG21 sollte versuchen, die Liste solcher Dinge auf dem neuesten Stand zu halten. Aber ich werde jeden zur Kenntnis nehmen, der sagt "es wird den ABI brechen" und mit mir im selben Raum ist.

Was wollen wir noch ändern?


Ich weiß nicht. Und ich weiß nicht, was ich nicht weiß. Aber wenn ich gebeten würde zu raten, würde ich Folgendes sagen:

  • C++23 ABI, - , ABI.
  • , , , , ABI
  • ABI,
  • , ABI
  • Tombstone ABI

ABI


Während der letzten ABI-Diskussion wurden in Prag eine Reihe von Umfragen durchgeführt, die jedoch nichts aussagen. Je nachdem, ob Sie ein Pessimist oder ein Optimist sind, können die aktuellen Ergebnisse von Ihnen unterschiedlich interpretiert werden.

Wichtige Fakten:

  • WG21 will ABI in 23 nicht brechen
  • WG21 hält es für notwendig, den ABI in zukünftigen Versionen von C ++ (C ++ 26 oder höher) zu brechen.
  • WG21 wird einige Zeit brauchen, um Vorschläge zu prüfen, die gegen ABI verstoßen
  • WG21 verspricht keine ewige Stabilität
  • WG21 hält es für wichtig, der Leistung Vorrang einzuräumen, auch zum Nachteil der Sprachstabilität

Diese Aussagen haben viele wichtige Punkte, aber es gibt keinen Konsens. Seltsamerweise teilte sich das Komitee in zwei Hälften.

Wahrsagen


In welcher Version von C ++ soll auf Änderungen gewartet werden?


Der offensichtliche Nachteil all dieser Umfragen ist, dass wir nicht entschieden haben, wann genau wir den ABI brechen wollen.

in c ++ 23? Nein, definitiv noch nicht.

in C ++ 26? Einige Leute beabsichtigen zu stimmen, aber ein anderer Teil wird wahrscheinlich für C ++ 41 stimmen oder für die Zeit, in der sie in Rente gehen und ihr aktuelles Projekt nicht unterstützen müssen. Eine der gerade erwähnten Fragen C ++ - einige ; sehr bequem!

Es gibt keinen Grund zu der Annahme, dass das ABI später verletzt werden kann, wenn es jetzt nicht verletzt werden kann. Menschen, die Stabilität brauchen, sind mehrere Jahre hinter dem Standard zurück. Wenn wir es jetzt nicht brechen, werden sich die Menschen weiterhin auf den nie versprochenen ABI verlassen, vielleicht noch zehn oder sogar zwanzig Jahre. Die einfache Tatsache, dass wir diese Umfrage durchgeführt haben, hat letztendlich dafür gestimmt, den ABI nicht zu verletzen, zeigt, dass das gesamte Ökosystem allmählich stagniert und stagniert - mit jedem Tag wird das Problem nur noch schlimmer und möglicherweise teurer.

Ich glaube nicht, dass sich an der in drei Jahren durchgeführten Umfrage etwas ändern wird. Es ist wie mit der globalen Erwärmung: Alle sind sich einig, dass wir dieses Problem eines Tages angehen müssen. Und dann lasst uns Diesel im Jahr 2070 verbieten?

Alles, was in den nächsten fünf Jahren nicht geplant ist, wird wahrscheinlich nie passieren.

Über Angebote, die gegen ABI verstoßen


WG21 stimmte dafür, mehr Zeit für Vorschläge zu verwenden, die gegen das derzeitige ABI verstoßen. Dies bedeutet ein paar Dinge:

  • Wir werden mehr Zeit in einem der lautesten Räume des Ausschusses verschwenden, um dieses Thema zu erörtern, und weniger auf Vorschläge verzichten, die mehr Chancen auf Annahme haben, und sie am Ende trotzdem ablehnen
  • Wir werden nach Alternativen suchen, die ABI nicht brechen (dies wird unten diskutiert).
  • Teilweise Änderungen des ABI können eingeführt werden (siehe auch unten)

Leistung ist wichtiger als ABI-Stabilität


Es ist wie zu fragen, ob ein Fünfjähriger eine Süßigkeit will. Natürlich werden wir über die Bedeutung der Leistung abstimmen. Ich mache mir jedoch Sorgen, dass einige Leute immer noch dagegen gestimmt haben.

Es scheint mir, dass der Ausschuss gleichzeitig auf zwei Stühlen gleichzeitig sitzen möchte. Und das ist unmöglich:
Bryce Adelstein Lelbach @blebach
- Leistung
- Stabilität ABI
- Fähigkeit, etwas zu ändern

Wählen Sie zwei Optionen aus den vorgeschlagenen aus.

Die Stabilität der Sprache und des ABI kollidieren natürlich miteinander und zwingen uns, eine so grundlegende Frage zu stellen: Was ist C ++ und was ist seine Standardbibliothek?

In diesem Fall werden normalerweise die Begriffe „Leistung“, „ Null-Kosten- Abstraktion“ und „ Zahlen Sie nicht für das, was Sie nicht verwendengespeichert . Und die Stabilität von ABI steht für all dies.

Weitreichende Konsequenzen


Bild

Ich bin zutiefst davon überzeugt, dass die Entscheidung, den ABI im 23. Jahr nicht zu brechen, der größte Fehler ist, den das Komitee jemals gemacht hat. Und ich weiß, dass manche Leute das Gegenteil glauben. Aber hier ist, was wahrscheinlich bald passieren wird:

Albtraum des Lernens


Lass uns ehrlich sein. Alle Programme, die auf ABI basieren, verstoßen wahrscheinlich irgendwo gegen ODR- Prinzipien oder verwenden inkompatible Flags, die zum Glück immer noch funktionieren.

Neue Programme müssen aus dem Quellcode kompiliert werden. Wir benötigen Tools, die auf der Assembly aus den Quellen basieren, und keine Sammlung von Bibliotheken, die wir von irgendwoher erhalten und irgendwie in das Projekt eingefügt haben.

Ja, das Bauen aus der Quelle ist nicht so einfach zu erreichen. Wir müssen diesen Ansatz für das Produkt jedoch fördern und die Compiler regelmäßig aktualisieren, damit die Benutzer einen Monat nach der Veröffentlichung und nicht zehn Jahre später von den neu eingeführten Funktionen profitieren. Richtige, zuverlässige, skalierbare und reproduzierbare Lösungen, Open Source-Bibliotheken und ein Abhängigkeitssystem müssen gefördert werden.

Das Komitee weigert sich, gegen ABI zu verstoßen und erklärt offen, dass es schlecht geschriebene Programme während ihrer gesamten Existenz unterstützen wird. Auch wenn Sie keine Verknüpfung zu den durch apt-install erhaltenen Bibliotheken herstellen (die eigentlich für das System bestimmt sind), gibt es andere Personen, da das Komitee ihnen ihren Segen gegeben hat.

Dies ist ein großer Schritt zurück. Wie können wir anderen gute Sprachpraktiken beibringen, wenn wir keinen Anreiz dazu haben?

Verlust des Interesses an der Standardbibliothek


Der geschätzte Verlust an Bibliotheksleistung aufgrund unserer mangelnden Bereitschaft, gegen ABI zu verstoßen, wird auf 5-10% geschätzt. Diese Zahl wird nur mit der Zeit wachsen. Schauen wir uns Beispiele an:

  • Wenn Sie ein großes Unternehmen sind, können Sie sich ein neues Rechenzentrum kaufen oder ein Team von Programmierern bezahlen, die ihre eigene Bibliothek unterstützen
  • , 5% ,
  • , 5-10% , VR-
  • , —

Ich denke, hier stellt sich wohl oder übel die Frage: "Ich sollte auf jeden Fall C ++ und seine Standardbibliothek verwenden!" und „Vielleicht sollte ich die Standardbibliothek nicht verwenden? Oder sollte ich C ++ grundsätzlich nicht verwenden? Vielleicht wäre .NET, Julia oder Rust eine bessere Lösung? “ Natürlich gibt es viele Faktoren, die die Antwort beeinflussen, aber wir sehen, was in letzter Zeit passiert.

Viele Spieleentwickler stehen der Standardbibliothek äußerst skeptisch gegenüber. Sie würden lieber ihre eigene Alternative wie EASTL entwickeln , als STL zu nutzen. Facebook hat Torheit , Google hat Abseilen und so weiter.

Es ist wie ein Schneeball. Wenn Benutzer die Standardbibliothek nicht verwenden, haben sie kein Interesse daran, sie zu verbessern. Leistung ist der Schlüsselfaktor, der die Bibliothek am Leben erhält. Ohne Leistungsgarantie wird viel weniger Aufwand in die Entwicklung gesteckt.
>> Jonathan Müller @foonathan
Was bringt es, Container aus der Standardbibliothek zu verwenden, wenn sie keine bessere Leistung bieten?

Titus Winters @TitusWinters
Vielleicht, weil sie häufig und leicht zugänglich sind? (Diese beiden Tatsachen bedeuten nicht dasselbe).
Die Abstimmung zur Erhaltung von ABI ist wie die Aussage, dass die Standardbibliothek McDonald's sein sollte - er ist auch überall, er ist stabil und löst die Aufgaben technisch.

Wie kann ein Ausschuss Vorschläge prüfen, die einen ABI brechen?


Als Schmerzlinderung werden verschiedene Optionen angeboten, die durch die Unfähigkeit, Angebote anzunehmen, verursacht werden, wenn sie gegen den ABI verstoßen:

Neue Namen hinzufügen


Bild

Dies ist die erste und naheliegende Lösung. Wenn wir uns nicht ändern können std::unordered_map, können wir einfach hinzufügen std::fast_map? Es gibt mehrere Gründe, warum dies schlecht ist. Das Hinzufügen von Typen zur Standardbibliothek ist sowohl in Bezug auf die Supportkosten als auch in Bezug auf die Ausbildung teuer. Nach der Einführung der neuen Klasse werden unweigerlich Tausende von Artikeln erscheinen, in denen erklärt wird, welcher Container verwendet werden soll. Soll ich zum Beispiel std::scoped_lockoder verwenden std::lock_guard? Ich habe keine Ahnung! Ich muss jedes Mal googeln. Es gibt auch das Problem, dass gute Namen früher oder später enden. Wir bekommen auch etwas Overhead während der Programmausführung, da alle Container ständig ineinander konvertiert werden müssen, es schwierig wird, eine große Anzahl von Konvertierungsüberladungen in der Klasse usw. zu kontrollieren.

Es ist ironisch, aber diejenigen, die die obige Lösung unterstützen, können auch argumentieren, dass C ++ eine zu komplexe Sprache ist. Das Hinzufügen von Duplikaten zur Bibliothek wird es definitiv nicht einfacher machen.

Aber wir könnten dieses Angebot als Standard annehmen!


Einige Bibliotheksentwickler behaupten, dass ihre Angebote aufgrund eines ABI-Verstoßes abgelehnt wurden, obwohl sie tatsächlich nichts verletzt haben, oder sie könnten geändert werden, um einen ABI-Fehler zu umgehen.

Als zynische Person fällt es mir schwer zu glauben. Tatsache ist, dass es zuvor keine derartigen Vorschläge gab und die Szenarien, in denen sie angewendet werden können, sehr begrenzt sind. ABI Review Group (ARG) könnte in dieser Angelegenheit helfen, aber sie werden wahrscheinlich wieder einen anderen Namen für die Klasse / Funktion empfehlen.

Teilweise Abi-Verletzung


Die Hauptidee besteht nicht darin, den gesamten ABI zu brechen, sondern ihn nur für eine bestimmte Klasse oder Funktion zu ändern. Das Problem bei diesem Ansatz ist, dass anstelle des Fehlers in der Verknüpfungsphase das Problem bereits beim Start des Programms auftritt, was uns unangenehm überrascht. Das Komitee hatte diesen Ansatz bereits in C ++ 11 ausprobiert, als es das Markup änderte std::string. Daraus wurde nichts Gutes. Alles war so schlecht, dass diese Tatsache immer noch als Argument für die Aufrechterhaltung des aktuellen ABI verwendet wird.

Eine weitere Indizierungsebene


Eine Lösung für einige der Probleme mit ABI wäre die Möglichkeit, über einen Zeiger auf die Daten der Klasse zuzugreifen. Dann wäre das Markup der Klasse genau dieser Zeiger. Die Idee kommt der PIMPL-Sprache sehr nahe, die aufgrund ihres ABI in Qt aktiv verwendet wird . Ja, das würde das Problem mit den Klassenmitgliedern lösen, aber was tun mit virtuellen Methoden?

In Anbetracht eines kritischeren Problems sprechen wir über das Hinzufügen einer weiteren Indirektionsebene (Zeigerindex) und einer zusätzlichen Speicherzuweisung im Heap für alles, was im Rahmen von ABI enthalten ist. In STL ist tatsächlich alles in diesem Framework enthalten, da es sich um eine Sammlung verallgemeinerter Klassen handelt.

Infolgedessen wird der Preis für diesen Ansatz enorm sein.

Als Lösung für dieses Problem enthält der Standard bereits mehrere Vorschläge. Einige von ihnen möchten PIMPL zu einem der Merkmale der Sprache machen, sodass Sie zwischen ABI-Stabilität und hoher Leistung wählen können.

Ironischerweise müssen wir jedoch den ABI brechen, um Bibliothekstypen in PIPML-Typen umzuwandeln.

Bauen Sie den gesamten Code alle drei Jahre neu zusammen


Nur meine Gedanken laut.

Alle aktuellen Angebote im Standard müssen vernichtet werden


Paradoxerweise war C ++ noch nie so lebendig wie jetzt. In Prag arbeiteten 250 Menschen an vielen Dingen für ihn, darunter:

  • Numerik
  • Lineare Algebra
  • Audio
  • Unicode
  • Asynchrone E / A.
  • 2D- und 3D-Grafiken
  • Viele andere Funktionen

Alle diese Vorschläge vereinen sich in einer gemeinsamen Tatsache: Sie sind im Vergleich zu dem, was wir derzeit im Standard haben, viel optionaler. Die Menschen versuchen einfach, Dinge aus ihrem Forschungs- und Arbeitsbereich oder dem, was sich ständig weiterentwickelt und verändert, zu standardisieren.
Insbesondere Unicode-Algorithmen sind extrem instabil und ändern sich im Laufe der Zeit schnell.

Und dann zeichnet sich ein Horror wie Networking ab . Es ist sehr, sehr verantwortungslos zu versuchen, alles zu standardisieren, was zu Sicherheitsproblemen führen könnte, und es später nicht ändern zu können (denken Sie an ABI).

Da C ++ beschlossen hat, es stabil zu machen, müssen alle diese Vorschläge zerstört und gebrannt werden. Ich würde nicht zerstört werden wollen, aber das muss getan werden.

Aber sie werden es immer noch nicht tun.

Im besten Fall werden wir in einer der neuen Versionen von C ++ keine Fehler machen und den aktuellen Stand der Dinge standardisieren und dann alles langsam zersetzen, da es nicht möglich ist, dies zu beheben (im Fall von Networking TS scheinen wir daher überhaupt nichts ändern zu können Wir müssen das, was vor zehn Jahren existierte, standardisieren, dann kann die Bibliothek natürlich noch erheblich verbessert werden, aber lassen wir diese Geschichte für ein anderes Mal.

Aber natürlich werden wir viele, viele Fehler machen.

>> Ólafur Waage @olafurw
( , )

, !

. , ( : , , )?

Hyrum Wright @hyrumwright
, , . — , .

Einige Fehler werden absichtlich gemacht, da es sich um Kompromisse handelt, während andere viele Jahre lang unbemerkt bleiben.

Die Zeit vergeht, aber die Standardbibliothek steht still. Zuvor gemachte Kompromisse stören uns allmählich und werden später zu echten „Engpässen“ im bestehenden Code.

Einige Dinge können wirklich nicht geändert werden, da sie in die API eingebettet sind. Wir alle haben eine Vorstellung davon, wie schwierig es ist, eine vorhandene API zu ändern. Ein Teil des Codes kann jedoch noch repariert und verbessert werden, wenn wir den ABI brechen könnten.

C ++ wird in den nächsten 40 Jahren noch flott sein. Wenn wir nicht erkennen können, dass es zu irgendeinem Zeitpunkt auf unvorhersehbare Weise geändert werden muss, besteht der einzig richtige Schritt darin, dieses Spiel im Prinzip nicht zu spielen.

Jeder weiß, dass ein assoziativer Standardcontainer seit weniger als zehn Jahren für die Verwendung relevant ist. Aber warum glauben wir dann, dass größere Vorschläge im Standard erfolgreicher sein werden?

Ihr Angebot zum Standard wird zerstört, mein Angebot wird auf die gleiche Weise zerstört.

Kann ein Ausschuss einen ABI grundsätzlich brechen?


Viele sind sich sicher, dass das Komitee eine solche Entscheidung grundsätzlich nicht treffen kann, denn dann werden die Bibliotheksentwickler sie einfach ignorieren. All dies ähnelt schmerzhaft dem Armdrücken, bei dem das Komitee beschlossen hat, nicht zu spielen.

Tatsache ist jedoch, dass Entwickler von Produkten ihre eigenen Benutzer haben. Benutzer sind diejenigen, die zunächst verstehen müssen, welche Kompromisse ihnen auferlegt werden.

Viele Menschen verlassen sich ganz zufällig auf ABI, ohne eine fundierte Entscheidung zu treffen. Viele Menschen verlassen sich auch auf Stabilität, weil sich natürlich jeder darauf verlassen will. Aber wie alles andere hat Stabilität einen Preis, und jetzt zahlt sich das gesamte C ++ - Ökosystem dafür aus.

All Articles