Une question commune, ici et ailleurs. C ++ est-il adapté aux systèmes embarqués?
Des microcontrôleurs? RTOS? Grille-pain? PC intégrés?
La POO est-elle utile sur les microcontrôleurs?
C ++ supprime-t-il trop le programmeur du matériel pour être efficace?
Le C ++ d’Arduino (sans gestion de mémoire dynamique, modèles, exceptions) doit-il être considéré comme du "vrai C ++"?
(Espérons que ce wiki servira de lieu pour contenir cette guerre sainte potentielle)
microcontroller
embedded
programming
c++
Toby Jaffey
la source
la source
Réponses:
Oui, le C ++ est toujours utile dans les systèmes embarqués. Comme tout le monde l’a dit, cela dépend toujours du système lui-même, comme si un uC 8 bits serait probablement un non-non dans mon livre, même s’il existe un compilateur et que certaines personnes le font (frémir). Il existe toujours un avantage à utiliser le C ++, même lorsque vous le réduisez à quelque chose comme "C +", même dans un monde micro de 8 bits. Qu'est-ce que je veux dire par "C +"? Je veux dire, n'utilisez pas new / delete, évitez les exceptions, évitez les classes virtuelles avec héritage, évitez éventuellement l'héritage ensemble, soyez très prudent avec les modèles, utilisez des fonctions inline au lieu de macros et utilisez des
const
variables au lieu de#defines
.Je travaille à la fois en C et en C ++ dans des systèmes embarqués depuis plus de 10 ans maintenant, et mon enthousiasme juvénile pour le C ++ s’est définitivement dissipé en raison de problèmes réels qui ébranlent la naïveté de chacun. J'ai vu le pire de C ++ dans un système embarqué que je voudrais appeler "les programmeurs CS devenus fous dans un monde EE". En fait, c’est quelque chose sur lequel je travaille avec mon client pour améliorer cette base de code qu’ils ont parmi d’autres.
Le danger du C ++ réside dans le fait qu’il s’agit d’un outil très puissant qui ressemble beaucoup à une épée à deux tranchants qui peut vous couper le bras et la jambe si elle n’est pas éduquée et disciplinée correctement dans son langage et sa programmation générale. C ressemble plus à une épée à simple tranchant, mais toujours aussi forte. Avec C ++, il est trop facile d’obtenir des niveaux d’abstraction très élevés et de créer des interfaces obscurcies qui perdent toute signification à long terme, et ce en partie du fait de la flexibilité du C ++ dans la résolution du même problème avec de nombreuses fonctionnalités de langage différentes (modèles, OOP, procédures, etc.). RTTI, modèles POO +, surcharge, inlining).
J'ai terminé deux séminaires de 4 heures sur les logiciels embarqués en C ++, donnés par le gourou du C ++, Scott Meyers. Il a souligné certaines choses sur les modèles que je n'avais jamais envisagées auparavant et sur le fait qu'elles peuvent contribuer davantage à la création d'un code essentiel pour la sécurité. En bref, vous ne pouvez pas avoir de code mort dans un logiciel qui doit répondre à des exigences strictes en matière de code de sécurité. Les modèles peuvent vous aider à accomplir cela, car le compilateur crée uniquement le code dont il a besoin lors de l'instanciation des modèles. Cependant, il faut mieux connaître leur utilisation pour concevoir correctement cette fonctionnalité plus difficile à réaliser en C, car les lieurs ne permettent pas toujours d'optimiser le code mort.
Scott Meyers est un très grand partisan des modèles et de l'utilisation judicieuse de l'inline, et je dois dire que je suis toujours sceptique quant à l'idée de parler de modèles. J'ai tendance à les fuir, même s'il dit qu'elles ne devraient être appliquées que là où elles deviennent le meilleur outil. Il souligne également que C ++ vous donne les outils nécessaires pour créer de très bonnes interfaces, faciles à utiliser correctement et rendant difficile l’utilisation erronée. Encore une fois, c'est la partie difficile. Il faut atteindre un niveau de maîtrise en C ++ avant de pouvoir savoir comment appliquer ces fonctionnalités de la manière la plus efficace possible pour devenir la meilleure solution de conception.
La même chose vaut pour la programmation orientée objet. Dans le monde intégré, vous devez vous familiariser avec le type de code que le compilateur va cracher pour savoir si vous pouvez gérer les coûts d'exécution du polymorphisme d'exécution. Vous devez également être disposé à prendre des mesures pour prouver que votre conception respecte les délais impartis. Est-ce que cette nouvelle classe InterruptManager va rendre ma latence d'interruption trop longue? Il existe d'autres formes de polymorphisme qui peuvent mieux convenir à votre problème, telles que le polymorphisme en temps de liaison, ce que C peut également faire, mais C ++ peut le faire via le modèle de conception Pimpl (pointeur Opaque) .
Je dis cela pour dire que le C ++ a sa place dans le monde embarqué. Vous pouvez détester tout ce que vous voulez, mais cela ne va pas disparaître. Il peut être écrit de manière très efficace, mais il est plus difficile d’apprendre à le faire correctement qu'avec C. Cela peut parfois être plus efficace que C pour résoudre un problème et parfois exprimer une meilleure interface, mais encore une fois, vous devez Renseignez-vous et n'ayez pas peur d'apprendre comment.
la source
C ++ convient parfaitement aux systèmes embarqués. J'utilise maintenant la présence / l'absence de bons outils de développement (ou leur absence) comme critère principal pour utiliser ou non un microprocesseur particulier.
Les zones de C ++ qui sont bonnes à utiliser sur les systèmes embarqués, car leurs coûts de ressources sont faibles:
Zones OK:
Zones à ne pas utiliser, principalement en raison de la surcharge d'exécution qui est inacceptable sur les petits systèmes:
la source
foo
appelsbar
dans un bloctry
/ créent des objets et des appels , ce qui génère une exception, le système doit en quelque sorte appeler les destructeurs pour les objets créés avant de rendre le contrôle . À moins que les exceptions ne soient complètement désactivées, vous ne pourrez pas savoir si vous pouvez en lancer une, et vous devez donc inclure du code supplémentaire pour permettre cette possibilité. J'aimerais voir une variante du C ++ avec des "exceptions vérifiées" pour gérer cela; si des routines qui pourraient permettre aux exceptions de s'échapper ...catch
bar
boz
bar
foo
bar
boz
add r15,r14,#2
au lieu demov r15,r14
; pour sortir par l' intermédiaire d' exception,ldrhs r0,[r14] / add r15,r14,r0
. Coût de cycle nul pour la sortie normale et aucune restriction de trame de pile.Oui, C ++ est certainement adapté aux systèmes embarqués. Commençons par clarifier quelques idées fausses sur la différence entre C et C ++:
Dans un micro intégré, vous aurez toujours besoin d'utiliser des langages de haut niveau avec précaution si vous vous préoccupez de contraintes de temps ou d'espace. Par exemple, de nombreux MCU ne gèrent pas bien les pointeurs et sont donc très inefficaces lors de l'utilisation de la pile. Cela signifie que vous devez faire attention à ne pas transmettre de variables à des fonctions, à l'aide de tableaux et de pointeurs, et à la récursivité. Une simple ligne de C comme:
peut générer environ 4 pages d’instructions en fonction de la nature de ces variables.
Chaque fois que vous utilisez un langage de haut niveau et que vous vous préoccupez de contraintes de temps et d'espace, vous devez savoir comment chaque fonctionnalité de cette langue se traduit par des instructions machine sur votre MCU (au moins, chaque fonctionnalité que vous utilisez). Ceci est vrai pour C, C ++, Ada, peu importe. Toutes les langues contiendront probablement des fonctionnalités qui ne traduiront pas efficacement sur les petites MCU. Vérifiez toujours les listes de désassemblage pour vous assurer que le compilateur ne génère pas une quantité d'instructions pour quelque chose de trivial.
C convient-il aux MCU intégrés? Oui, tant que vous gardez un œil sur le code généré.
C ++ est-il adapté aux MCU intégrés? Oui, tant que vous gardez un œil sur le code généré.
Voici pourquoi je pense que le C ++ est meilleur que le C même sur les MCU 8 bits: C ++ offre un support amélioré pour:
Aucune de ces caractéristiques n’est plus lourde que les caractéristiques typiques de C.
Lorsque vous déplacez des MCU 16 ou 32 bits, il devient logique d'utiliser des fonctionnalités plus lourdes de C (pile, tas, pointeurs, tableaux, printf, etc.). De la même manière, un MCU plus puissant devient approprié utiliser des fonctionnalités plus lourdes de C ++ (pile, tas, références, STL, nouveau / supprimer).
Donc, inutile de frémir à la pensée de C ++ sur un PIC16. Si vous connaissez bien votre langue et votre MCU, vous saurez les utiliser efficacement.
la source
a[i] = b[j] * c[k];
peut générer environ 4 pages d'instructions en fonction de la nature de ces variables." Si votre MCU / compilateur le fait, c'est que vous utilisez un processeur amateur de garage des années 80.Je trouve toujours ces débats divertissants à lire. Pas tant pour la discussion intellectuelle sur les avantages et les inconvénients des différentes langues disponibles, mais parce que vous pouvez généralement déterminer la position de quelqu'un sur le sujet en fonction de son travail, de son expérience ou de son domaine d'intérêt. Les arguments de «l'optimisation prématurée» sont à la hauteur des arguments avancés par les majors CS et les programmeurs de maintenance citant Knuth à gauche et à droite et par ceux qui travaillent dans le monde réel où la performance compte pour être fous (je suis membre de ce dernier groupe être juste).
À la fin de la journée, vous pouvez développer un excellent logiciel en C ou C ++ ou insérer un langage ici . Cela dépend des capacités du développeur et non du langage. Etre un expert dans une langue n’est généralement requis que si vous avez choisi la mauvaise langue pour commencer et que vous devez maintenant l’inciter à résoudre votre problème. Dans la plupart des cas, il s’agit là des seules situations dans lesquelles vous devez plonger dans des fonctionnalités obscures ou un compilateur. astuces pour atteindre l'objectif.
J'entends souvent les gens commencer ces arguments comme "Je suis un expert en langage X et bla bla" Je discrédite honnêtement immédiatement ces gens car, à mon avis, ils ont déjà abordé le problème sous le mauvais angle et tout ce qui a ensuite été corrompu. par leur désir d'utiliser leur outil pour résoudre le problème et montrer à quel point il est 'cool'.
Je vois souvent les développeurs choisir un ensemble d’outils d’abord et tenter de le résoudre ensuite, ce qui est complètement faux et donne lieu à des solutions merdiques.
Comme je l'ai mentionné dans un commentaire à une autre réponse, ces guerres linguistiques se résument souvent en argumentant que la langue X permet au programmeur de faire plus de bêtises. Bien que divertissantes à lire, toutes ces affirmations signifient vraiment que vous avez un problème pour engager de bons développeurs et que vous devez vous attaquer directement à ce problème plutôt que d'essayer de résoudre le problème en continuant à embaucher de mauvais développeurs et en choisissant des outils tels qu'ils puissent faire aussi bien. dommage possible.
À mon avis, les bons développeurs, qu'il s'agisse de développement de logiciels ou de matériel informatique, recherchent le problème, élaborent une solution et trouvent les outils qui leur permettent d'exprimer la solution de la "meilleure façon". Peu importe que l'outil requis soit quelque chose que vous n'ayez jamais utilisé auparavant. Après avoir utilisé 3-4 langages / outils de développement pour des projets, en choisir un nouveau devrait avoir un impact minimal sur votre temps de développement.
Bien entendu, le «meilleur moyen» est un terme subjectif et doit également être défini au cours de la phase de recherche. Il faut prendre en compte une multitude de problèmes: performances, facilité d’expression, densité du code, etc. en fonction du problème rencontré. Je n'ai pas inclus la maintenabilité dans cette liste pour une raison quelconque, peu importe la langue que vous choisissez, si vous avez choisi l'outil approprié et pris le temps de comprendre le problème, cela devrait venir «gratuitement». La difficulté de maintenir le code est souvent le résultat du choix d’un mauvais outil ou d’une structure de système médiocre. Il en résulte un désordre odieux pour le faire fonctionner.
Revendiquer n'importe quelle langue est "meilleure" que n'importe quelle autre est stupide sans définir un problème d'intérêt particulier. Une approche orientée objet n'est pas toujours meilleure qu'une approche fonctionnelle. Certains problèmes se prêtent très bien à un paradigme de conception orienté objet. Beaucoup ne le font pas. La même déclaration peut être faite à propos de nombreuses fonctionnalités linguistiques que les gens semblent aimer utiliser.
Si vous passez plus de 20% de votre temps à résoudre un problème de saisie de code, vous produisez probablement un système très médiocre ou des développeurs très médiocres (ou vous êtes encore en train d'apprendre). Vous devriez consacrer la majeure partie de votre temps au début à schématiser le problème et à déterminer les interactions entre différents éléments de l'application. Coller un groupe de développeurs talentueux dans une salle avec un marqueur et un problème à résoudre et leur dire qu’ils ne sont pas autorisés à écrire du code ou à choisir des outils tant qu’ils ne sont pas à l’aise avec le système tout entier en fera plus pour améliorer la qualité des fichiers. développement de la production et de la vitesse que le choix de tout nouvel outil chaud garanti pour améliorer le temps de développement. (regardez le développement de Scrum comme référence pour le contraire opposé à mon argument)
Souvent, la triste réalité est que beaucoup d'entreprises ne peuvent mesurer la valeur d'un développeur que par le nombre de lignes écrites ou par la «production tangible». Ils considèrent les 3 semaines passées dans une pièce avec un tableau comme une perte de productivité. Les développeurs sont souvent obligés d'accélérer le stade de développement de la "pensée" ou d'utiliser un outil défini par un problème politique au sein de l'entreprise: "Le frère de mon patron travaille pour IBM afin que nous ne puissions utiliser que leurs outils", ce genre de déchets. . Ou pire, vous obtenez un ensemble d'exigences en constante évolution de la part de l'entreprise, qui n'est pas en mesure de réaliser une étude de marché adéquate ou qui ne comprend pas l'impact des changements sur le cycle de développement.
Désolé d’être un peu en marge de ce discours, j’ai des opinions bien arrêtées sur ce sujet.
la source
Toute langue peut convenir à un système intégré. Embedded signifie simplement: fait partie d'un appareil plus volumineux, par opposition à un ordinateur libre d'utilisation.
La question a plus de pertinence lorsqu'on lui demande un système (en temps réel) ou à ressources limitées .
Pour un système temps réel, le langage C ++ est l’un des langages les plus élevés qui soit toujours approprié lors de la programmation pour des contraintes de temps strictes. À l'exception de l'utilisation de tas (opérateur libre), il n'a pas de construction dont le temps d'exécution est indéterminé. Vous pouvez donc vérifier si votre programme remplit ses exigences de synchronisation. Avec un peu plus d'expérience, vous pourriez même le prédire. Bien entendu, il convient d'éviter l'utilisation de tas, bien que le nouvel opérateur puisse toujours être utilisé pour une attribution unique. Les constructions que C ++ offre sur C peuvent être utilisées à bon escient dans un système embarqué: OO, exceptions, templates.
Pour les systèmes très limités en ressources (puces 8 bits, moins de quelques ko de RAM, pas de pile accessible), le C ++ complet pourrait ne pas convenir, bien qu'il puisse tout de même être utilisé comme "meilleur C".
Je pense qu'il est regrettable qu'Ada ne soit utilisé que dans certaines niches. À bien des égards, il s'agit d'un Pascal ++, mais sans la charge d'être compatible vers le haut avec un langage qui était déjà un véritable gâchis. (edit: le désordre sérieux est bien sûr que C. Pascal est un langage beau mais quelque peu impraticable.)
=============================================== ==============
EDIT: Je tapais une réponse à une nouvelle question ("Dans quels cas le C ++ est-il nécessaire lorsque nous programmons des microcontrôleurs"?) Qui était fermé en référence à celui-ci, je vais donc ajouter ce que j’ai écrit:
Il n'y a jamais de raison absolue d'utiliser un langage de programmation, mais il peut y avoir des arguments qui ont plus ou moins de poids dans une situation donnée. Les discussions à ce sujet peuvent être trouvées à de nombreux endroits, avec des positions allant de "ne jamais utiliser le C ++ pour un micro-contrôleur" à "toujours utiliser le C ++". Je suis plus avec la dernière position. Je peux donner quelques arguments, mais vous devrez décider vous-même quel poids ils ont dans une situation donnée (et dans quelle direction).
Mon blog a quelques écrits sur l'utilisation de C ++ sur de petits systèmes (= micro-contrôleurs).
la source
D'après mon expérience, C ++ est généralement mal adapté aux petits systèmes embarqués. Je veux dire par microcontrôleurs et périphériques sans système d'exploitation.
De nombreuses techniques de programmation orientée objet C ++ reposent sur une allocation de mémoire dynamique. Cela fait souvent défaut dans les petits systèmes.
STL et Boost démontrent réellement la puissance du C ++, les deux étant extrêmement volumineux.
C ++ encourage le programmeur à faire abstraction de la machine, où elle doit être adoptée dans les systèmes contraints.
L'année dernière, j'ai porté un produit commercial de bureau à distance sur des téléphones mobiles. Il a été écrit en C ++ et fonctionnait sous Windows, Linux et OSX. Mais il s’appuyait fortement sur les exceptions STL, la mémoire dynamique et C ++. Pour réussir sur les environnements WinCE, Symbian et sans système d'exploitation, une réécriture en C était l'option la plus saine.
la source
J'espère ajouter plus de lumière que de chaleur à cette discussion sur le C ++ sur des systèmes nus et à ressources limitées.
Problèmes en C ++:
Les exceptions sont particulièrement un problème de RAM car le "tampon d'urgence" requis (où l'exception de mémoire insuffisante va par exemple) peut être plus grand que la RAM disponible et constitue certainement un gaspillage pour les microcontrôleurs. Pour plus d'informations, voir n4049 et n4234 . Ils doivent être désactivés (comportement non spécifié pour le moment, assurez-vous de ne pas les jeter). Le SG14 travaille actuellement sur de meilleurs moyens de le faire.
RTTI ne vaut probablement jamais la surcharge, il devrait être désactivé
De grandes versions de débogage, bien que cela ne pose pas de problème dans le développement de bureau classique, si le débogage ne tient pas sur la puce, cela peut poser problème. Le problème provient du code basé sur un modèle ou des appels de fonction supplémentaires ajoutés pour plus de clarté. Ces appels de fonctions supplémentaires seront à nouveau supprimés par l'optimiseur et la clarté ou la flexibilité supplémentaires peuvent constituer un avantage considérable. Toutefois, cela peut poser problème dans les versions de débogage.
Allocation de tas. Bien que la STL permette l'utilisation d'allocateurs personnalisés, cela peut être complexe pour la plupart des programmeurs. L'allocation de segment de mémoire est non déterministe (c.-à-d. Pas en temps réel difficile) et la fragmentation peut entraîner des situations inattendues de mémoire insuffisante malgré le travail effectué dans les tests. La tenue de livres nécessaire au tas afin de garder trace de l’espace libre et de la taille variable peut poser problème avec les petits objets. Il est généralement préférable d’utiliser l’allocation de pool (en C et C ++), mais cela peut être anormal pour les programmeurs C ++ habitués à utiliser uniquement le tas.
Le polymorphisme à l'exécution et les autres appels indirects sont généralement un gros problème de performances. Le problème est généralement davantage dû au fait que l'optimiseur ne peut pas voir au-delà d'eux davantage que l'extraction et le saut réels à l'adresse. Pour cette raison, les appels indirects doivent être évités en C et C ++ où, comme en C ++, ils sont plus enracinés dans la culture (et sont très utiles dans d'autres domaines).
l'interfaçage implicite avec Clib peut être problématique. Il peut sembler contre-intuitif que les problèmes de clib appartiennent à la catégorie C ++, mais le problème provient du partage implicite de ressources dans des environnements concurrents (le partage est plus explicite en C). L’utilisation de l’implémentation newLib courante entraîne souvent beaucoup de problèmes, ce qui n’est généralement pas nécessaire dans les UC, par contre newLibNanno n’est pas réentrant, de sorte que son accès doit être sérialisé (simplifié ici). C'est un problème pour C aussi mais l'accès est plus explicite. En règle générale, vous ne devez en principe utiliser rien de namespace std dans le contexte ISR, à moins que vous ne soyez sûr qu'il n'accède pas à l'état dans clib (errorno ou le tas, par exemple). C'est également important si vous utilisez des threads (je préfère RTC) pour remplacer new et delete afin de synchroniser l'accès à malloc et free.
En conclusion, C ++ a quelques problèmes mais ils sont essentiellement tous réparables ou évitables.
Maintenant pour C, ici le problème est d'ordre supérieur. Je n’ai pas la capacité syntaxique en C d’abstraire les choses de manière à pouvoir optimiser ou vérifier les invariants au moment de la compilation. Par conséquent, je ne peux pas encapsuler correctement des éléments de manière à ce que l'utilisateur n'ait pas besoin de savoir comment ils fonctionnent pour pouvoir les utiliser et la plupart de mes erreurs sont détectées à l'exécution (ce qui est non seulement trop tard, mais entraîne également des coûts supplémentaires). La seule façon d'être générique en C est de passer par les données. Je passe une chaîne de format à printf ou scanf, qui est évaluée au moment de l'exécution, par exemple. Il est alors assez difficile pour le compilateur de prouver que je n'utilise pas certaines des options théoriquement possibles lorsque les bonnes données sont transmises, ce qui signifie une génération potentielle de code mort et une perte de potentiel d'optimisation.
Je sais que je suis peut-être en train de déchaîner une merde ici, mais mon expérience des microcontrôleurs 32 bits est que dans une comparaison de pommes à pommes de C et C ++ écrits par des experts (comme en C ++, potentiellement très basés sur des modèles), C ++ est le langage beaucoup plus efficace dès que tout doit être générique (comme dans n'importe quelle bibliothèque) et ils sont essentiellement équivalents dans des cas non génériques. Il est également plus facile pour un novice de tirer parti de l’expertise d’un développeur expert de bibliothèques en C ++.
En même temps, il y a vraiment vraiment peu de fonctions pour lesquelles je ne peux pas transmettre de données incorrectes, dès que l'entrée n'est pas un int, mais
something
pour lequel j'utilise un int comme méthode de représentation, il y a un potentiel pour l'obtenir faux (passe une valeur invalide ou un "otherThing" plutôt qu'un "quelque chose"). En C, ma seule méthode pour vérifier si l'utilisateur s'est trompé est au moment de l'exécution. En C ++, j'ai la possibilité d'effectuer certaines vérifications, pas toutes, mais certaines vérifications au moment de la compilation, qui sont gratuites.À la fin de la journée, une équipe C est souvent aussi puissante que son programmeur le plus faible et l’avantage du code obtenu est un multijoueur de 1 ou une pénalité de performance. Ce que je veux dire par là, c’est soit des performances élevées pour un et un seul travail unique dans un environnement unique comportant des décisions de conception uniques, soit il est suffisamment générique pour être utilisé dans plusieurs environnements (autre microcontrôleur, autre stratégie de gestion de la mémoire, autre latence, etc.). compromis de débit, etc., etc.), mais a un coût de performance inhérent.
En C ++, les éléments peuvent être encapsulés par des experts et utilisés dans de nombreux environnements où la génération de code temporel de compilation s’adapte à la tâche spécifique et où la vérification statique empêche les utilisateurs de faire des choses stupides à un coût nul. Ici, nous avons beaucoup moins de compromis entre être générique et être rapide et, par conséquent, du point de vue des coûts et des avantages, nous utilisons le langage le plus performant, le plus sûr et le plus productif.
La critique selon laquelle il existe toujours une grande pénurie de bonnes bibliothèques C ++ incorporées peut conduire à des décisions pragmatiques consistant à utiliser principalement le C sur un compilateur C ++. Les décisions d'utiliser uniquement le C dans un projet sont essentiellement dictées par des considérations idéologiques, par nécessité d'un support hérité ou par l'admission que l'équipe n'est pas assez disciplinée pour s'abstenir d'un ensemble très sélectif de choses stupides que l'on peut faire en C ++ mais pas en C et en même temps assez discipliné pour ne pas faire le plus grand ensemble de bêtises que l'on ne peut pas se protéger en C mais que l'on pourrait en C ++.
la source
Mon expérience: formation tout juste sortie de l’école sous l’ancienne programmation de Bell Labs; travaille depuis 3 ans, 2 sur un projet de recherche de premier cycle; acquisition de données / contrôle de processus en VB.NET. A passé un an et demi à travailler sur une application de base de données d'entreprise dans VB6. Travaille actuellement sur un projet pour PC embarqué avec 2 Go de stockage, 512 Mo de RAM, 500 MHz x86; plusieurs applications s'exécutant simultanément écrites en C ++ avec un mécanisme IPC entre les deux. Oui je suis jeune
Mon avis: Je pense que C ++ peut fonctionner efficacement compte tenu de l'environnement que j'ai écrit ci-dessus . Certes, les performances en temps réel difficiles ne sont pas une exigence de l'application utilisée, et dans certaines applications intégrées, cela peut poser problème. Mais voici les choses que j'ai apprises:
C ++ est fondamentalement différent de C (c'est-à-dire qu'il n'y a pas de C / C ++). Bien que tout ce qui est valide en C soit valide en C ++, le C ++ est un langage très différent et il est nécessaire d’apprendre à programmer en C ++, pas en C, pour l’utiliser efficacement dans n’importe quelle situation. En C ++, vous devez programmer de manière orientée objet, non pas de manière procédurale, ni un hybride des deux (grandes classes avec beaucoup de fonctions). En général, vous devriez vous concentrer sur la création de petites classes avec peu de fonctions et composer toutes les petites classes en une solution plus grande. Un de mes collègues m'a expliqué que je programmais de manière procédurale dans des objets, ce qui est un véritable gâchis et qui est difficile à maintenir. Lorsque j'ai commencé à appliquer des techniques plus orientées objet, j'ai constaté que la facilité de maintenance / lisibilité de mon code était améliorée.
C ++ fournit des fonctionnalités supplémentaires sous la forme d'un développement orienté objet qui peut fournir un moyen de simplifier le code pour en faciliter la lecture / la maintenance . Honnêtement, je ne pense pas qu'il y ait beaucoup d'amélioration de l'efficacité de la performance / de l'espace dans la programmation orientée objet. Mais je pense que la POO est une technique qui peut aider à diviser un problème complexe en plusieurs petits morceaux. Et cela est utile pour les personnes qui travaillent sur le code, un élément de ce processus qui ne devrait pas être ignoré.
De nombreux arguments contre C ++ ont principalement à voir avec l'allocation dynamique de mémoire. C a ce même problème aussi. Vous pouvez écrire une application orientée objet sans utiliser de mémoire dynamique, même si l'un des avantages de l'utilisation des objets est que vous pouvez affecter ces éléments de manière dynamique de manière simple. Tout comme en C, vous devez faire attention à la façon de gérer les données pour réduire les fuites de mémoire, mais la technique RAII simplifie cela en C ++ (créer une destruction dynamique de la mémoire en l'encapsulant dans des objets). Dans certaines applications, où chaque emplacement de mémoire compte, cela peut s'avérer trop difficile à gérer.
MODIFIER:
la source
Oui, le problème avec C ++ est l’empreinte accrue du code.
Dans certains systèmes, vous comptez les octets et dans ce cas, vous devrez accepter un coût d’exploitation aussi proche des limites de vos systèmes, ce qui augmente les coûts de développement de C.
Mais, même en C, pour un système bien conçu, vous devez tout garder encapsulé. Les systèmes bien conçus sont difficiles et le C ++ offre aux programmeurs une place pour une méthode de développement très structurée et contrôlée. Il y a un coût à apprendre la programmation orientée objet, et si vous souhaitez y basculer, vous l'acceptez beaucoup. Dans de nombreux cas, la direction préfère continuer avec C et ne pas payer le coût, car il est difficile de mesurer les résultats d'un changement augmente la productivité. Vous pouvez voir un article du gourou des systèmes intégrés, Jack Ganssle, ici .
La gestion dynamique de la mémoire est le diable. Pas vraiment, le diable est auto-routé, la gestion de la mémoire dynamique fonctionne très bien sur un PC, mais vous pouvez vous attendre à redémarrer un PC toutes les deux semaines au moins. Vous constaterez que lorsqu'un système intégré continue de fonctionner pendant 5 ans, la gestion dynamique de la mémoire peut vraiment être gâchée et même commencer à échouer. Ganssle discute de choses comme pile et tas dans son article.
Certaines choses en C ++ sont plus susceptibles de poser des problèmes et utilisent beaucoup de ressources, la suppression de la gestion de la mémoire dynamique et des modèles est une étape importante pour conserver l'empreinte de C ++ plus proche de l'empreinte de C. Cela reste du C ++, vous n'avez pas besoin de dynamique gestion de la mémoire ou des modèles pour écrire un bon C ++. Je n'avais pas réalisé qu'ils supprimaient les exceptions, je considère les exceptions comme une partie importante de mon code que je supprime dans la version, mais que j'utilise jusqu'à ce point. Lors des tests sur le terrain, des exceptions peuvent générer des messages pour m'informer d'une exception interceptée.
la source
Je pensais que ce discours anti-C ++ de Linus Torvalds était intéressant.
Il ne parle pas du monde des systèmes intégrés, mais du développement du noyau Linux. Pour moi, la pertinence découle de ceci: C ++ nécessite de comprendre un contexte plus large, et je peux apprendre à utiliser un ensemble de modèles d'objet, je ne me fie pas à moi-même de les mémoriser lorsque je dois mettre à jour le code dans quelques mois.
(D'autre part, je travaille actuellement sur un périphérique intégré utilisant Python (et non pas C ++, mais utilisant le même paradigme de programmation orientée objet) qui posera exactement ce problème. Pour ma défense, il s'agit d'un système intégré assez puissant pour être appelé PC. Il ya 10 ans.)
la source
Je pense que d’autres réponses ont très bien exposé le pour et le contre et les facteurs de décision, alors je voudrais juste résumer et ajouter quelques commentaires.
Pour les petits microcontrôleurs (8 bits), pas question. Vous demandez simplement de vous blesser, il n'y a aucun gain et vous perdrez trop de ressources.
Pour les microcontrôleurs haut de gamme (par exemple 32 bits, 10 ou 100 Mo pour la RAM et le stockage) dotés d’un système d’exploitation correct, c’est tout à fait correct et, j’oserais dire, même ceux qui sont recommandés.
La question est donc: où est la limite?
Je ne sais pas avec certitude, mais une fois que j’ai développé un système pour un uC 16 bits avec 1 Mo de RAM et 1 Mo de stockage en C ++, je le regretterai plus tard. Oui, cela a fonctionné, mais le travail supplémentaire que j'ai fait n'en valait pas la peine. Je devais le mettre en forme, m'assurer que des exceptions telles que des exceptions ne produiraient pas de fuites (le support OS + RTL était plutôt bogué et peu fiable). De plus, une application OO utilise généralement beaucoup de petites allocations, et les frais généraux qui en découlent étaient un autre cauchemar.
Compte tenu de cette expérience, je suppose que pour les projets futurs, je choisirai le C ++ uniquement dans les systèmes d'au moins 16 bits et d'au moins 16 Mo pour la mémoire vive et le stockage. C'est une limite arbitraire, et cela variera probablement en fonction du type d'application, des styles de codage et des idiomes, etc. Cependant, étant donné les mises en garde, je recommanderais une approche similaire.
la source
Certaines fonctionnalités de C ++ sont utiles dans les systèmes intégrés. Il y en a d'autres, comme les exceptions, qui peuvent coûter cher et dont les coûts ne sont pas toujours apparents.
Si j'avais mes compétences, il y aurait un langage populaire qui combine le meilleur des deux mondes et qui inclut certaines caractéristiques qui manquent dans les deux langues; certains fournisseurs incluent quelques-unes de ces fonctionnalités, mais il n'y a pas de normes. Quelques choses que j'aimerais voir:
Je sais que le père du C ++ n’apprécie pas trop une version du C ++ incorporée, mais je pense qu’elle pourrait offrir des améliorations considérables par rapport à l’utilisation de C.
Quelqu'un sait si quelque chose comme ce qui précède est envisagé pour tout type de norme?
la source
C ++ est plus qu'un langage de programmation:
a) C'est un "meilleur" C b) C'est un langage orienté objet c) C'est un langage qui nous permet d'écrire des programmes génériques
Bien que toutes ces fonctionnalités puissent être utilisées séparément, les meilleurs résultats sont obtenus lorsque les trois d'entre elles sont utilisées simultanément. Néanmoins, si vous choisissez de n'en choisir qu'un, la qualité du logiciel embarqué augmentera.
a) C'est un "meilleur" C
C ++ est un langage typé fort; plus fort que C. Vos programmes bénéficieront de cette fonctionnalité.
Certaines personnes ont peur des pointeurs. C ++ inclut les références. Fonctions surchargées.
Et cela vaut la peine de dire: Aucune de ces fonctionnalités n’est générée par des programmes plus importants ou plus lents.
b) C'est un langage orienté objet
Quelqu'un a dit dans cet article qu'abstraction de la machine dans les microcontrôleurs n'est pas une bonne idée. Faux! Nous tous, ingénieurs intégrés, avons toujours fait abstraction de la machine, à l’aide d’une autre méthode que celle du C ++. Le problème que je vois avec cet argument est que certains programmeurs ne sont pas habitués à penser aux objets, c'est pourquoi ils ne voient pas les avantages de la POO.
Lorsque vous êtes prêt à utiliser le périphérique d'un microcontrôleur, il est probable que le périphérique a été extrait pour nous (de vous-même ou d'un tiers) sous la forme du pilote de périphérique. Comme je l'ai dit précédemment, ce pilote utilise le code C, comme le montre l'exemple suivant (tiré directement d'un exemple de NXP LPC1114):
/ * Configuration de la minuterie pour le match et l’interruption à TICKRATE_HZ * /
Chip_TIMER_Reset (LPC_TIMER32_0);
Chip_TIMER_MatchEnableInt (LPC_TIMER32_0, 1);
Chip_TIMER_SetMatch (LPC_TIMER32_0, 1, (timerFreq / TICKRATE_HZ2));
Chip_TIMER_ResetOnMatchEnable (LPC_TIMER32_0, 1);
Chip_TIMER_Enable (LPC_TIMER32_0);
Voyez-vous l'abstraction? Ainsi, lors de l'utilisation de C ++ dans le même but, l'abstraction passe au niveau supérieur grâce au mécanisme d'abstraction et d'encapsulation du C ++, à un coût nul!
c) C'est un langage qui nous permet d'écrire des programmes génériques
Les programmes génériques sont réalisés au moyen de modèles, et les modèles ne génèrent également aucun coût pour nos programmes.
De plus, le polymorphisme statique est obtenu avec des modèles.
Méthodes virtuelles, RTTI et exceptions.
Il existe un compromis lors de l'utilisation de méthodes virtuelles: un meilleur logiciel contre une pénalité de performances. Cependant, rappelez-vous qu'une liaison dynamique est susceptible d'être implémentée à l'aide d'une table virtuelle (un tableau de pointeurs de fonction). J'ai souvent fait la même chose en C (même régulièrement), aussi je ne vois pas les inconvénients liés à l'utilisation de méthodes virtuelles. De plus, les méthodes virtuelles en C ++ sont plus élégantes.
Enfin, un conseil sur RTTI et les exceptions: NE LES UTILISEZ PAS dans les systèmes embarqués. Evitez-les à tout prix !!
la source
Mon fond, intégré (mcu, pc, unix, autre), en temps réel. Critique de sécurité. J'ai présenté un ancien employeur à STL. Je ne fais plus ça.
Du contenu de flamme
C ++ est-il adapté aux systèmes embarqués?
Meh C ++ est une douleur à écrire et à maintenir. C + est un peu correct (n'utilisez pas certaines fonctionnalités)
C ++ dans les microcontrôleurs? RTOS? Grille-pain? PC intégrés?
Encore une fois je dis Meh. C + n'est pas si mal, mais l'ADA est moins douloureuse (et c'est vraiment dire quelque chose). Si vous êtes chanceux comme moi, vous devez faire de la Java intégrée. Un accès contrôlé à la matrice et l'absence d'arithmétique de pointeur permettent d'obtenir un code très fiable. Les garbage collectors dans Java intégré ne sont pas prioritaires, et la mémoire et la réutilisation des objets sont étendues. Un code bien conçu peut donc être exécuté à tout jamais sans GC.
La POO est-elle utile sur les microcontrôleurs?
Bien sûr est. L'UART est un objet ..... Le DMAC est un objet ...
Les machines à états d'objet sont très faciles.
C ++ supprime-t-il trop le programmeur du matériel pour être efficace?
Sauf s’il s’agit d’un PDP-11, C n’est pas votre processeur. C ++ étant à l’origine un pré-processeur sur C, Bjarne Stroustrup ne se moquerait plus d’avoir simulé des simulations lentes alors qu’il était chez AT & T. C ++ n'est pas votre processeur.
Allez chercher un MCU qui exécute des bytecodes java. Programme en Java. Rire les gars C.
Le C ++ d’Arduino (sans gestion de mémoire dynamique, modèles, exceptions) doit-il être considéré comme du "vrai C ++"?
Nan. tout comme tous les compilateurs C bâtardés pour MCU.
À l’avenir, Java intégré ou ADA intégré sont normalisés (ish); tout le reste est chagrin.
la source
Les systèmes intégrés sont conçus pour effectuer certaines tâches spécifiques, plutôt que d'être un ordinateur à usage général pour plusieurs tâches. Un système intégré est une combinaison de matériel informatique et de logiciels. C est la mère de toutes les langues modernes. C'est un langage bas, mais puissant, qui parle tout et qui traite de tout type de matériel. C / C ++ est donc un choix optimal pour développer un logiciel pour système embarqué, ce qui est très complet pour chaque système embarqué. Comme nous le savons, C est un langage en développement. Le système d'exploitation UNIX est écrit en C. Parce que le développement de logiciels réussit souvent à sélectionner le meilleur langage pour un projet donné, il est surprenant de constater que le langage C / C ++ s'est avéré approprié pour les processeurs 8 bits et 64 bits. ; dans les systèmes avec octets, kilooctets et mégaoctets de mémoire. C a l'avantage de l'indépendance du processeur, ce qui permet aux programmeurs de se concentrer sur des algorithmes et des applications, plutôt que sur les détails d'une architecture de processeur particulière. Cependant, nombre de ces avantages s'appliquent également aux autres langages de haut niveau. Mais C / C ++ a réussi là où tant d’autres langages ont largement échoué?
la source
<rant>
Je pense que C ++ est un langage de merde en premier lieu. Si vous souhaitez utiliser la POO, écrivez des programmes Java. C ++ ne fait rien pour appliquer les paradigmes de programmation orientée objet, car l'accès direct à la mémoire est tout à fait en votre pouvoir.
Si vous avez un MCU, vous parlez probablement de moins de 100 Ko de mémoire flash. Vous voulez programmer dans un langage dont l'abstraction de la mémoire est: lorsque je déclare une variable ou un tableau, il obtient de la mémoire, un point; malloc (alias "nouveau" mot clé en C ++) devrait être plus ou moins banni des logiciels embarqués, sauf peut-être dans de rares occasions, un appel lors du démarrage du programme.
Bon sang, il y a (fréquemment) des temps dans la programmation intégrée où le C n'est pas assez bas, et vous devez faire des choses comme allouer des variables aux registres et écrire un assemblage en ligne pour renforcer vos routines de service d'interruption (ISR). Des mots-clés tels que "volatile" deviennent diablement importants à comprendre. Vous passez beaucoup de temps à manipuler la mémoire au niveau du bit , pas au niveau de l' objet .
Pourquoi voudriez-vous vous leurrer en pensant que les choses sont plus simples qu'elles ne le sont réellement?
</ rant>
la source