URL: https://linuxfr.org/users/xilun666/journaux/le-glissement-du-c-et-dans-une-moindre-mesure-du-c-vers-une-position-indesirable Title: Le glissement du C++ (et dans une moindre mesure du C) vers une position indésirable Authors: Guillaume Knispel Date: 2019年10月25日T21:29:28+02:00 License: CC By-SA Tags: Score: 9 Bonjour Nal ! Dans son article [Should you learn C to "learn how the computer works"?](https://words.steveklabnik.com/should-you-learn-c-to-learn-how-the-computer-works), Steve Klabnik nous narrait des éléments de l'histoire du C standard ainsi que sur la distinction subtile entre sa "machine abstraite" et d'un côté une machine concrète, de l'autre une machine virtuelle visant encore plus de portabilité (e.g. la JVM). Début Octobre il remet le couvert sur ce thème et précise avec ["C is not how the computer works" can lead to inefficient code](https://words.steveklabnik.com/c-is-not-how-the-computer-works-can-lead-to-inefficient-code). Les deux articles sont intéressants en soit et je recommande leur lecture. Et j'en profite pour tenter de lancer un petit débat sur LinuxFr sur un thème lié : vers où le C++ va, et est-ce une position utile et tenable à _long_ terme ? (oui Steve parlait du C, mais je vais focaliser un peu plus sur le C++, vous allez voir pourquoi, même si le C suit le mouvement et que donc je désigne en fait un peu les deux -- par la suite j'écrirai simplement C++) Concernant le "long" dans "long terme", je précise tout de suite que non, je ne crois pas que le C++ va mourir en 10 ans ni même en 20 quels que soient ses défauts, mais que le Cobol non plus n'est toujours pas mort aujourd'hui, et ne va pas mourir non plus. Le C++ a effectivement été normalisé en décrivant une machine abstraite. Mais ce qui n'était au début qu'un élément de langage servant à permettre l'expression effective du standard (devant par définition entre autre préciser un dénominateur commun) est rentré depuis au cœur des compilateurs et plus précisément dans les passes d'optimisations, conçues dès lors principalement pour répondre aux spécifications de la machine abstraite et guère au-delà, même potentiellement dans des cas tordus engendrant des risques ("exploitation" des UB, c'est à dire optimisations très avancées par hypothèse de leur absences). Ces risques sont non seulement de plus en plus amplifiés avec l'augmentation de la visibilité des compilos (par exemple le LTO), en plus d'être d'une _nature_ particulièrement problématique de base dans un monde à la connectivité réseau déjà ultra étendue et continuant à croître. Ils existent d'une manière ambiante dans ces langages et donc potentiellement dans le code écrit avec (d'une manière toute aussi ambiante : pas de section safe/unsafe), étant donné le peu d'analyseurs statiques fiables et l'indécidabilité du problème dans le cas général (même si on peut restreindre les programmes sources acceptés pour l'analyse pour éviter ce risque, mais à quel point ? et quel est alors l’intérêt face à un langage qui incorpore de base les "restrictions" et l'analyse qu'elles permettent ?). Même de relativement récents ajouts dans le C++ n'inversent pas la tendance - au contraire - malgré : 1/ la fameuse efficacité des compilateurs capables de calculer des propriétés sur les variables et/ou de sortir des tests des boucles, réduisant l'impact du e.g. bound checking (à noter que ce genre d'opti peut être pratiqué d'une manière totalement non-risquée lorsque les hypothèses sont prouvées au lieu d'être simplement supposées, et à défaut certainement au moins en maîtrisant le risque fortement) 2/ l'efficacité redoutable des processeurs modernes, y compris certains relativement "légers" sur téléphone portable (ainsi hors hyper-threading le bound checking peut devenir souvent quasi-gratuit, même si le compilateur n'a pas réussi à trop l'optimiser, grâce à de l'OOO très profond et de la spéculation). Ainsi par exemple std::span ne propose même pas d'API d'accès avec indices vérifiés, ce qui est selon moi et vu ce que j'ai exposé précédemment, profondément ridicule. De plus même lorsque des API plus sûres existent, elles sont typiquement plus laborieuse à utiliser (.at() au lieu de [], value() au lieu de * ou ->), alors que les besoins en perfs sont typiquement concentrés et non pas diffus, tandis que le besoin en sécurité _par défaut_ croit. Et je ne parle même pas de la possibilité même d'exprimer dans ce contexte certains types de code : par exemple je ne suis pas sûr du tout qu'il soit possible d’implémenter un allocateur généraliste en C++ standard strictement conforme (+ primitives d'alloc de page auprès de l'OS, par exemple) -- et si c'est possible je suis sûr que ça nécessite plusieurs jours d'études poussées de la norme (en plus de toute connaissance nécessaire sur les allocateurs) Bref pensez-vous que le C++ fait fausse route sur ce thème (surtout en 2019...), ou que chaque cycle compte *même* sur du code sur lequel on ne lance pas de profileur, *même* lorsque ce code traite directement ou indirectement des données potentiellement manipulables, et *même* vu les difficultés que ça engendre auprès des programmeurs (sans compter ceux qui sont même pas au courant de ce bordel) Et est-ce que ça va mener à sa perte dans un monde hyperconnecté ? Ou est-ce quelque chose le sauvera (les contrats peut-être ?) Sur ce cher Nal, bon Trolldi !