Dans Quand utiliser C sur C ++ et C ++ sur C? il y a une déclaration concernant. pour coder la taille / les exceptions C ++:
Jerry répond (entre autres points):
(...) il est généralement plus difficile de produire des exécutables vraiment petits avec C ++. De toute façon, vous écrivez rarement beaucoup de code dans les systèmes vraiment petits (...)
ce à quoi j'ai demandé pourquoi, Jerry a répondu:
L'essentiel est que C ++ inclue la gestion des exceptions, ce qui (du moins généralement) ajoute un minimum à la taille de l'exécutable. La plupart des compilateurs vous permettent de désactiver la gestion des exceptions, mais lorsque vous le faites, le résultat n'est plus tout à fait C ++. (...)
dont je ne doute pas vraiment au niveau technique réel.
Par conséquent, je suis intéressé (par pure curiosité) à entendre des exemples concrets dans lesquels un projet a choisi le langage C ++ comme langage, puis a choisi de désactiver les exceptions. (Ne vous contentez pas simplement de "ne pas utiliser" d'exceptions dans le code utilisateur, mais désactivez-les dans le compilateur, de sorte que vous ne puissiez pas lancer ou capturer des exceptions.) Pourquoi un projet a-t-il choisi de le faire (toujours en utilisant C ++ et non C, mais pas exceptions) - quelles sont / étaient les raisons (techniques)?
Addendum: Pour ceux qui souhaitent développer leurs réponses, il serait agréable de détailler la manière dont les implications de l'absence d'exception sont gérées:
- Les collections STL (
vector
, ...) ne fonctionnent pas correctement (les échecs d'allocation ne peuvent pas être signalés) new
ne peut pas jeter- Les constructeurs ne peuvent pas échouer
la source
Réponses:
Presque tous les jeux de console existants sont en C ++ avec une exception désactivée, même de nos jours. En fait, c'est la configuration par défaut pour les compilateurs C ++ ciblant ces consoles. Parfois, il n'est pas garanti que certaines fonctionnalités C ++ fonctionnent correctement sur ces compilateurs, comme l'héritage multiple (je pense à un compilateur par défaut de console très connu, par exemple).
En outre, un autre exemple est le SDK matériel Arduino utilisant gcc sans exception, activé en C ++, et d’autres choses comme aucune STL fournie .
Il y a des raisons techniques, bonnes ou mauvaises, peu importe, ce n'est pas mon conseil mais les raisons que j'ai entendues:
Je pense que les exceptions peuvent être utiles même dans les jeux, mais il est vrai que sur les jeux sur console, ce n'est pas vraiment utile.
Mise à jour:
J'ajoute un autre exemple surprenant ici: LLVM / CLang n'utilise pas exception ni RTTI pour les raisons suivantes :
CLang est bien connu pour sa rapidité de compilation et ses erreurs explicites, mais aussi pour son compilateur rare qui possède un code très facile à suivre.
la source
Jerry a déclaré: ... le résultat n'est plus tout à fait C ++ , alors que, selon ma métaphore, il s'agit clairement de C ++, un dialecte légèrement différent , car les programmes utilisent d'autres formes, conventions et styles écrits.
Voici mes principales raisons pour les désactiver:
Compatibilité binaire
Le fait de croiser les frontières de la langue et de la traduction n’est pas universellement bien défini ni indéfini. Si vous voulez garantir que votre programme fonctionne dans le domaine de comportement défini, vous devrez mettre les exceptions en quarantaine aux points de sortie du module.
Taille exécutable
Voici les tailles binaires d'un programme sans exception que j'ai écrit, construit sans et avec les exceptions activées:
Sans exception:
Avec des exceptions:
Rappel: Il s’agit d’un ensemble de bibliothèques et de programmes ne contenant aucun jet / attrape. Le drapeau du compilateur fait activer des exceptions dans la bibliothèque standard C de. Par conséquent, le coût dans le monde réel est supérieur à 19% dans cet exemple.
Compilateur: apple gcc4.2 + llvm. Tailles en MB.
La vitesse
Malgré l'expression "exceptions à coût zéro", ils ajoutent encore des frais généraux même lorsque rien ne se produit jamais. Dans le cas ci-dessus, il s'agit d'un programme critique en termes de performances (traitement du signal, génération, présentation, conversions, avec de grands ensembles de données / signaux, etc.). Les exceptions ne sont pas une caractéristique nécessaire dans cette conception, alors que les performances sont très importantes.
Exactitude du programme
Cela semble être une raison étrange ... Si lancer n’est pas une option, vous devez écrire des programmes relativement stricts, corrects et bien testés pour vous assurer que votre programme s’exécute correctement et que les clients utilisent correctement les interfaces (si vous me donnez un mauvais argument vérifiez pas un code d'erreur, alors vous méritez UB). Le résultat? La qualité de la mise en œuvre s'améliore considérablement et les problèmes sont résolus rapidement.
Simplicité
Les implémentations de gestion des exceptions ne sont pas souvent mises à jour. Ils ajoutent également beaucoup de complexité car une implémentation peut avoir beaucoup de nombreuses séquences de sortie. Il est plus simple de lire et de gérer des programmes très complexes lorsqu'ils utilisent un petit ensemble de stratégies de sortie bien définies, typées et qui sortent du lot et sont gérées par le client. Dans d'autres cas, les implémentations peuvent au fil du temps implémenter plus de lancers ou leurs dépendances peuvent les introduire. Les clients ne peuvent pas se défendre facilement ou adéquatement contre toutes ces issues. J'écris et mets à jour beaucoup de bibliothèques, il y a des évolutions et améliorations fréquentes. Essayer de garder tout cela synchronisé avec les séquences de sortie d'exception (dans une base de code volumineuse) ne serait pas une bonne utilisation du temps, et ajouterait probablement beaucoup de bruit et de crudité. En raison de l'exactitude du programme et de la multiplication des tests,
Histoire / Code existant
Dans certains cas, ils n'ont jamais été introduits pour des raisons historiques. Une base de code existante ne les utilisait pas, la modification des programmes pouvait prendre des années-hommes et rendre vraiment moche à maintenir en raison du chevauchement des conventions et des mises en œuvre.
Inconvénients
Bien sûr, il y a des inconvénients, les plus importants sont: l'incompatibilité (y compris binaire) avec d'autres bibliothèques et le fait que vous devrez implémenter une bonne quantité de programmes pour s'adapter à ce modèle.
la source
malloc
retours0
), l’allocateur entre un élémentwhile (1)
comportant un commutateur de contexte, suivi d’une nouvelle tentative d’allocation. Dans cette base de code, ce qui était nouveau par le biais de l'allocateur pouvait renvoyer 0, mais la nouvelle implémentation a bien fonctionné. (suite)Google n'approuve pas les exceptions dans son Guide de style C ++ , principalement pour des raisons historiques:
(Souligné par l'éditeur)
la source
Qt n'utilise presque jamais d'exceptions. Les erreurs dans Qt sont signifiées par des codes d'erreur et des signaux. La raison officielle est:
Aujourd'hui, l'une des critiques courantes de Qt est que sa sécurité en matière d'exception n'est pas complète.
la source
Symbian C ++ (utilisé sur certains téléphones mobiles Nokia) n'utilise pas d'exceptions, du moins pas directement, car les compilateurs C ++ ne les ont pas implémentées de manière fiable lors du premier développement de Symbian.
la source
Je / jamais / utilise des exceptions. Il y a plusieurs raisons à cela, mais les deux principales sont que je n'ai jamais eu besoin d'eux pour produire un code robuste et qu'ils réduisent les performances lors de l'exécution.
J'ai travaillé sur un code de production qui utilise et désactive les exceptions - le code qui autorisait les exceptions était uniformément pire. À certains endroits, des exceptions ont été utilisées pour un véritable contrôle de flux plutôt que pour la gestion des erreurs, qui est très lourd, anti-performance et difficile à déboguer. En général, les problèmes de débogage dans le code d'exception rempli étaient plus difficiles que dans le code sans exception - en partie à cause de la pile et des difficultés intrinsèques du mécanisme d'exception, mais beaucoup plus que cela était dû au code paresseux qui était encouragé en tant que résultat d'avoir la gestion des exceptions disponible.
Il n’ya rien de grave en ce qui concerne les exceptions elles-mêmes / si vous ne vous souciez pas des performances / et n’avez pas le temps de faire quelque chose correctement - elles sont une fonctionnalité de langage pour la gestion des erreurs et un bon substitut pour un mécanisme de gestion des erreurs approprié. Cependant, il existe presque toujours / mieux / moyens de gérer les erreurs - comme avec votre propre logique (il est difficile de développer cela - c'est presque du bon sens). Si ce n'est pas votre erreur, mais provient d'une bibliothèque (par exemple, la bibliothèque standard), alors vous devez respecter le choix des exceptions ou avoir un crash, mais je remettrais toujours en question ce choix. Je n'ai jamais vu une situation où les exceptions étaient en fait la meilleure solution.
Les assertions sont plus faciles à déboguer, les codes d'erreur sont moins lourds ... entre les deux, si vous l'utilisez correctement, vous obtiendrez plus facilement une lecture, un débogage et une maintenance plus rapides du code. Ses victoires tout au long de ...
la source
Dans la norme de codage Joint Strike Fighter C ++ de Bjarne et. al., les exceptions sont interdites en raison des exigences très strictes des avions de combat en temps réel.
Cité dans la FAQ C ++ de Bjarne .
N'oubliez pas que C ++ exécute probablement la plus grande variété de logiciels de toutes les langues ...
la source
C'est un peu important dans la conception de bibliothèques C ++. Souvent, avec une interface C, il est assez désagréable de lancer une exception de votre bibliothèque tierce au client. Le fait est que si votre bibliothèque lance, vous supprimez un ensemble de clients qui l'auraient utilisée, étant donné qu'elle avait une garantie de non-lancement (quelle que soit la raison pour laquelle le client dispose d'une restriction sur les exceptions).
Personnellement, j’ai vu des exceptions abusées lorsque l’on demande à l’équipe de "lancer une exception" chaque fois que quelque chose de moins terrible se produit. Bien sûr, vous voyez l'erreur ici - l'exception a été lancée dans le code avant que quiconque ne sache quoi en faire. Ce projet a eu quelques accidents, car ces jets profonds risquaient de s’élever de temps en temps.
la source
Peut-être à cet égard, il convient de mentionner Embedded C ++ . Le C ++ embarqué est une variante du C ++ conçue (bien évidemment) pour les systèmes embarqués. Il s'agit essentiellement d'un sous-ensemble approprié de C ++, avec (entre autres) les modèles, les espaces de noms et la gestion des exceptions supprimés.
Je devrais ajouter que bien qu'EC ++ ait fait sensation quand il était nouveau, il semble que la plupart du temps, ils se soient relativement discrets. Je ne sais pas si les gens ont perdu tout intérêt, ou si leur première tentative a été tellement parfaite que personne n'a vu aucune raison de la gâcher depuis une dizaine d'années.
<closed captioning for the humor impaired>Yeah, right!</closed captioning>
la source
Un bon exemple est la programmation en mode noyau.
Vous pouvez y utiliser C ++ pour du code plus propre, mais sans exception. Il n’existe pas de bibliothèque d’exécution pour eux et la gestion des exceptions utilise trop de mémoire de pile, ce qui est très limité dans le noyau (j’ai expérimenté les exceptions C ++ dans le noyau Windows NT et les exceptions de lancement et de déroulement mangent une moitié de la pile disponible - très facile d’obtenir un dépassement de capacité de pile et planter tout le système).
En général, vous définissez vous-même
new
et lesdelete
opérateurs. J'ai aussi trouvé desplacement new
références rvalue a et c ++ 11 assez pratiques . Aucune STL ni aucune autre bibliothèque en mode utilisateur C ++ qui repose sur des exceptions ne peut être utilisée.la source
Lorsque vous essayez de garder la mémoire exécutable au minimum. Généralement effectué sur des systèmes embarqués (ou mobiles). Pour les applications de bureau, cela n’est jamais nécessaire, mais sur des serveurs, il peut être utile de prendre en compte autant de RAM que possible pour le serveur Web ou pour SQL.
la source