Una pregunta común, aquí y en otros lugares. ¿C ++ es adecuado para sistemas integrados?
Microcontroladores? RTOSes? Tostadoras? PC integradas?
¿OOP es útil en microcontroladores?
¿C ++ elimina el programador demasiado lejos del hardware para ser eficiente?
¿Debería considerarse C ++ de Arduino (sin administración dinámica de memoria, plantillas, excepciones) como "C ++ real"?
(Con suerte, este wiki servirá como un lugar para contener esta potencial guerra santa)
microcontroller
embedded
programming
c++
Toby Jaffey
fuente
fuente
Respuestas:
Sí, C ++ sigue siendo útil en sistemas integrados. Como todos los demás han dicho, todavía depende del sistema en sí, como un uC de 8 bits probablemente sería un no-no en mi libro a pesar de que hay un compilador y algunas personas lo hacen (estremecimiento). Todavía hay una ventaja de usar C ++ incluso cuando lo reduce a algo como "C +" incluso en un micro mundo de 8 bits. ¿Qué quiero decir con "C +"? Quiero decir, no use new / delete, evite excepciones, evite las clases virtuales con herencia, posiblemente evite la herencia por completo, tenga mucho cuidado con las plantillas, use funciones en línea en lugar de macros y use
const
variables en lugar de#defines
.He trabajado tanto en C como en C ++ en sistemas embebidos durante más de una década, y parte de mi entusiasmo juvenil por C ++ definitivamente ha desaparecido debido a algunos problemas del mundo real que sacuden la ingenuidad de uno. He visto lo peor de C ++ en un sistema embebido al que me gustaría referirme como "programadores de CS enloquecidos en un mundo de EE". De hecho, eso es algo en lo que estoy trabajando con mi cliente para mejorar este código base que tienen entre otros.
El peligro de C ++ se debe a que es una herramienta muy poderosa, muy parecida a una espada de dos filos que puede cortar tanto el brazo como la pierna si no se educa y se disciplina adecuadamente en su lenguaje y programación general. C es más como una espada de un solo filo, pero igual de afilada. Con C ++ es demasiado fácil obtener niveles de abstracción muy altos y crear interfaces ofuscadas que pierdan su significado a largo plazo, y eso se debe en parte a la flexibilidad de C ++ para resolver el mismo problema con muchas características de lenguaje diferentes (plantillas, OOP, procedimientos, RTTI, OOP + plantillas, sobrecarga, en línea).
Terminé dos seminarios de 4 horas sobre software embebido en C ++ por el gurú de C ++, Scott Meyers. Señaló algunas cosas sobre plantillas que nunca antes había considerado y cuánto más pueden ayudar a crear un código crítico para la seguridad. Lo esencial es que no puede tener un código muerto en el software que tiene que cumplir con los estrictos requisitos de código crítico para la seguridad. Las plantillas pueden ayudarlo a lograr esto, ya que el compilador solo crea el código que necesita al crear instancias de plantillas. Sin embargo, uno debe aprender más sobre su uso para diseñar correctamente esta característica, que es más difícil de lograr en C porque los enlazadores no siempre optimizan el código muerto.
Scott Meyers es un gran defensor de las plantillas y el uso juicioso de la alineación, y debo decir que todavía soy escéptico sobre ser entusiasta de las plantillas. Tiendo a alejarme de ellos, a pesar de que él dice que solo deben aplicarse donde se convierten en la mejor herramienta. También señala que C ++ le brinda las herramientas para crear interfaces realmente buenas que sean fáciles de usar correctamente y dificulten el uso incorrecto. De nuevo, esa es la parte difícil. Uno debe llegar a un nivel de dominio en C ++ antes de que pueda saber cómo aplicar estas características de la manera más eficiente para ser la mejor solución de diseño.
Lo mismo vale para OOP. En el mundo incrustado, debe familiarizarse con el tipo de código que el compilador va a escupir para saber si puede manejar los costos en tiempo de ejecución del polimorfismo en tiempo de ejecución. También debe estar dispuesto a realizar mediciones para demostrar que su diseño cumplirá con los requisitos de la fecha límite. ¿Esa nueva clase de InterruptManager hará que mi latencia de interrupción sea demasiado larga? Hay otras formas de polimorfismo que pueden adaptarse mejor a su problema, como el polimorfismo de tiempo de enlace que C también puede hacer, pero C ++ puede hacerlo a través del patrón de diseño Pimpl (puntero opaco) .
Lo digo todo para decir que C ++ tiene su lugar en el mundo incrustado. Puedes odiarlo todo lo que quieras, pero no va a desaparecer. Se puede escribir de una manera muy eficiente, pero es más difícil aprender cómo hacerlo correctamente que con C. A veces puede funcionar mejor que C para resolver un problema y, a veces, expresar una mejor interfaz, pero de nuevo, debe Edúcate y no tengas miedo de aprender cómo hacerlo.
fuente
C ++ es absolutamente adecuado para sistemas integrados. Ahora uso la presencia / ausencia de buenas herramientas de desarrollo (o la falta de ellas) como mi criterio principal para usar o no un microprocesador en particular.
Áreas de C ++ que son buenas para usar en sistemas integrados porque tienen bajos costos de recursos:
Áreas OK:
Áreas que no se deben usar, principalmente debido a la sobrecarga de tiempo de ejecución que es inaceptable en sistemas pequeños:
fuente
foo
llamabar
dentro de un bloquetry
/catch
ybar
crea algunos objetos y llamadasboz
, lo que arroja una excepción, el sistema tiene que llamar de alguna manera a los destructores de los objetosbar
creados antes de devolver el controlfoo
. A menos que las excepciones estén completamente deshabilitadas,bar
no habrá forma de saber siboz
podría lanzar alguna, y por lo tanto debe incluir un código adicional para permitir esa posibilidad. Me gustaría ver una variación de C ++ con "excepciones marcadas" para lidiar con eso; Si las rutinas que podrían permitir excepciones a escapar ...add r15,r14,#2
lugar demov r15,r14
; para salir a través de excepción,ldrhs r0,[r14] / add r15,r14,r0
. Costo de ciclo cero para la salida normal, y sin restricciones de marco de pila.Sí, C ++ es ciertamente adecuado para sistemas integrados. Primero aclaremos un par de ideas erróneas sobre la diferencia entre C y C ++:
En un micro integrado, siempre necesitará usar lenguajes de alto nivel con cuidado si le preocupan las limitaciones de tiempo o espacio. Por ejemplo, muchas MCU no manejan bien los punteros, por lo que son muy ineficientes cuando se usa la pila. Esto significa que debe tener cuidado al pasar variables a funciones, usar matrices y punteros, y la recursividad. Una línea simple de C como:
puede generar alrededor de 4 páginas de instrucciones dependiendo de la naturaleza de esas variables.
Cada vez que usa un lenguaje de alto nivel y le preocupan las limitaciones de tiempo y espacio, debe saber cómo cada característica de ese idioma se traduce en instrucciones de máquina en su MCU (al menos, cada característica que usa). Esto es cierto para C, C ++, Ada, lo que sea. Probablemente todos los idiomas contendrán características que no se traducen de manera eficiente en MCU pequeños. Siempre revise los listados de desensamblaje para asegurarse de que el compilador no esté generando montones de instrucciones para algo trivial.
¿Es C adecuado para MCU integradas? Sí, siempre y cuando vigiles el código generado.
¿C ++ es adecuado para MCU integradas? Sí, siempre y cuando vigiles el código generado.
He aquí por qué creo que C ++ es mejor que C incluso en MCU de 8 bits: C ++ proporciona un soporte mejorado para:
Ninguna de estas características es más pesada que las características típicas de C.
A medida que avanza hasta MCU de 16 o 32 bits, comienza a tener sentido usar características más pesadas de C (pila, montón, punteros, matrices, printf, etc.) De la misma manera, en una MCU más potente se vuelve apropiado para usar características más pesadas de C ++ (pila, montón, referencias, STL, nuevo / eliminar).
Por lo tanto, no hay necesidad de estremecerse ante la idea de C ++ en un PIC16. Si conoce su idioma y su MCU correctamente, sabrá cómo utilizarlos de manera eficaz.
fuente
a[i] = b[j] * c[k];
puede generar alrededor de 4 páginas de instrucciones dependiendo de la naturaleza de esas variables". Si su MCU / compilador hace esto, es porque está utilizando una CPU de aficionado de garaje de los años 80.Siempre encuentro estos debates entretenidos de leer. No tanto para la discusión intelectual sobre los pros y los contras de los diversos idiomas disponibles, sino porque generalmente puede vincular la postura de alguien sobre el tema en función de su trabajo / experiencia / área de interés. Está a la altura de los argumentos de "optimización prematura" en los que los expertos en CS y los programadores de mantenimiento citan a Knuth de izquierda a derecha y aquellos que trabajan en el mundo real donde el rendimiento importa piensan que están todos locos (soy miembro de este último grupo para ser justo).
Al final del día, puede desarrollar un excelente software en C o C ++ o insertar un lenguaje aquí . Todo se reduce a las capacidades del desarrollador, no al lenguaje. Ser un experto en un idioma generalmente solo se requiere si ha elegido el idioma equivocado para comenzar y ahora necesita deformarlo para resolver su problema, en la mayoría de los casos, estas son las únicas situaciones en las que necesita sumergirse en características oscuras o compilador trucos para lograr el objetivo.
A menudo escucho a las personas comenzar estos argumentos como "Soy un experto en el lenguaje X y bla, bla". Honestamente, desacredito de inmediato a estas personas porque, en mi opinión, ya han abordado el problema desde el ángulo equivocado y todo después de eso está contaminado. por su deseo de usar su herramienta para resolver el problema y mostrar cuán "genial" es.
A menudo veo a los desarrolladores elegir un conjunto de herramientas primero e intentar adaptarlo a su problema en segundo lugar, lo cual es completamente incorrecto y da como resultado soluciones basura.
Como mencioné en un comentario a otra respuesta, estas guerras lingüísticas a menudo se convierten en argumentar que el lenguaje X permite al programador hacer cosas más tontas. Si bien es entretenido leer, todas estas afirmaciones realmente significan que tiene un problema para contratar buenos desarrolladores y necesita abordar ese problema directamente en lugar de tratar de ayudar a la situación al continuar contratando malos desarrolladores y eligiendo herramientas para que puedan hacer tan poco Daño como sea posible.
En mi opinión, buenos desarrolladores, ya sea desarrollo de software o hardware, investigan el problema, diseñan una solución y encuentran las herramientas que les permitan expresar la solución de la "mejor manera". No debería importar si la herramienta requerida es algo que nunca ha usado antes, después de haber usado 3-4 idiomas / herramientas de desarrollo para proyectos que eligen una nueva debería tener un impacto mínimo en su tiempo de desarrollo.
Por supuesto, "la mejor manera" es un término subjetivo y también debe definirse en la fase de investigación. Es necesario considerar una multitud de problemas: rendimiento, facilidad de expresión, densidad de código, etc., según el problema en cuestión. No incluí la capacidad de mantenimiento en esa lista por una razón, no me importa el idioma que elija, si eligió la herramienta adecuada y se tomó el tiempo para comprender el problema, esto debería ser 'gratis'. El código difícil de mantener es a menudo el resultado de elegir la herramienta incorrecta o una estructura de sistema deficiente, esto da como resultado un feo desastre para que funcione.
Afirmar que cualquier idioma es "mejor" que cualquier otro es una tontería sin definir un problema particular de interés. Un enfoque orientado a objetos no siempre es mejor que un enfoque funcional. Hay algunos problemas que se prestan muy bien a un paradigma de diseño orientado a objetos. Hay muchos que no. Se puede hacer la misma afirmación sobre muchas características del lenguaje que las personas parecen disfrutar insistiendo.
Si pasa más del 20% de su tiempo en un problema al escribir código, probablemente esté produciendo un sistema muy pobre o tenga desarrolladores muy pobres (o todavía está aprendiendo). Debería pasar la mayor parte de su tiempo haciendo un diagrama inicial del problema y determinando cómo interactúan varias partes de la aplicación. Pegar a un grupo de desarrolladores talentosos en una habitación con un marcador y un problema que resolver y decirles que no se les permite escribir ningún código o elegir ninguna herramienta hasta que se sientan cómodos con todo el sistema hará más para mejorar la calidad del desarrollo de salida y velocidad que elegir cualquier nueva herramienta caliente garantizada para mejorar el tiempo de desarrollo. (busque el desarrollo de scrum como referencia para el polo opuesto a mi argumento)
A menudo, la desafortunada realidad es que muchas empresas solo pueden medir el valor de un desarrollador por la cantidad de líneas escritas o al ver 'resultados tangibles'. Ven las 3 semanas en una habitación con un marcador como una pérdida de productividad. Los desarrolladores a menudo se ven obligados a acelerar la etapa de desarrollo del "pensamiento" o se ven obligados a usar una herramienta establecida por algún problema político dentro de la empresa, "El hermano de mi jefe trabaja para IBM, por lo que solo podemos usar sus herramientas", ese tipo de basura . O, lo que es peor, obtiene un conjunto de requisitos en constante cambio por parte de la empresa porque no son capaces de realizar una investigación de mercado adecuada o no entienden el impacto de los cambios en el ciclo de desarrollo.
Perdón por estar un poco fuera de tema con este discurso, tengo opiniones bastante fuertes sobre este tema.
fuente
Cualquier idioma puede ser adecuado para un sistema integrado. Integrado solo significa: parte de un aparato más grande, a diferencia de una computadora de uso gratuito.
La pregunta tiene más relevancia cuando se solicita un sistema (difícil) en tiempo real o de recursos limitados .
Para un sistema en tiempo real, C ++ es uno de los lenguajes más altos que aún es apropiado cuando se programan restricciones de tiempo estrictas. Con la excepción del uso de almacenamiento dinámico (operador libre), no tiene construcciones que tengan un tiempo de ejecución indeterminado, por lo que puede probar si su programa cumple con sus requisitos de tiempo y, con algo más de experiencia, incluso podría predecirlo. Por supuesto, se debe evitar el uso del montón, aunque el nuevo operador todavía se puede usar para la asignación de una sola vez. Las construcciones que ofrece C ++ sobre C se pueden aprovechar en un sistema integrado: OO, excepciones, plantillas.
Para sistemas muy limitados en recursos (chips de 8 bits, menos de unos pocos Kb de RAM, sin pila accesible), C ++ completo podría no ser adecuado, aunque aún podría usarse como una 'mejor C'.
Creo que es desafortunado que Ada parezca usarse solo en algunos nichos. En muchos sentidos, es un Pascal ++, pero sin la carga de ser compatible con un lenguaje que ya era un desastre serio para empezar. (Editar: el desorden grave es, por supuesto, C. Pascal es un lenguaje hermoso pero poco práctico).
================================================== ==============
EDITAR: Estaba escribiendo una respuesta a una nueva pregunta ("¿En qué casos es necesario C ++ cuando estamos programando microcontroladores"?) Que se cerró en referencia a esta, así que agregaré lo que escribí:
Nunca hay una razón general para el uso de cualquier lenguaje de programación, pero puede haber argumentos que tengan más o menos peso en una situación particular. Las discusiones sobre esto se pueden encontrar en muchos lugares, con posiciones que van desde "nunca use C ++ para un microcontrolador" hasta "siempre use C ++". Estoy más con la última posición. Puedo dar algunos argumentos, pero tendrás que decidir por ti mismo cuánto peso tienen en una situación particular (y en qué dirección).
Mi blog tiene algunos escritos sobre el uso de C ++ en sistemas pequeños (= microcontroladores).
fuente
En mi experiencia, C ++ generalmente no es adecuado para pequeños sistemas integrados. Por lo que quiero decir, microcontroladores y dispositivos sin sistema operativo.
Muchas técnicas de C ++ OOP se basan en la asignación dinámica de memoria. Esto a menudo falta en sistemas pequeños.
STL y Boost realmente demuestran el poder de C ++, ambos tienen una gran huella.
C ++ alienta al programador a abstraer la máquina, donde en sistemas restringidos debe ser aceptada.
El año pasado, porté un producto comercial de escritorio remoto a teléfonos móviles. Fue escrito en C ++ y se ejecutó en Windows, Linux y OSX. Pero, dependía en gran medida de STL, memoria dinámica y excepciones de C ++. Para que funcione en entornos WinCE, Symbian y sin sistema operativo, una reescritura de C fue la opción más sensata.
fuente
Espero agregar más luz que calor a esta discusión sobre C ++ en sistemas con limitaciones de recursos y de metal desnudo.
Problemas en C ++:
Las excepciones son especialmente un problema de RAM, ya que el "búfer de emergencia" requerido (donde va la excepción de falta de memoria, por ejemplo) puede ser mayor que la RAM disponible y ciertamente es un desperdicio en los microcontroladores. Para más información ver n4049 y n4234 . Deben estar apagados (que actualmente es un comportamiento no especificado, así que asegúrese de no tirar nunca). SG14 está trabajando actualmente en mejores formas de hacerlo.
RTTI probablemente nunca valga la pena la sobrecarga, debe apagarse
Grandes construcciones de depuración, aunque esto no es un problema en el desarrollo de escritorio clásico si la depuración no cabe en el chip, puede ser un problema. El problema surge de código con plantilla o llamadas de función adicionales agregadas para mayor claridad. El optimizador eliminará nuevamente estas llamadas de función adicionales y la claridad o flexibilidad añadidas puede ser una gran ventaja, sin embargo, en las versiones de depuración esto puede ser un problema.
Asignación de montón. Aunque el STL permite el uso de asignadores personalizados, esto puede ser complejo para la mayoría de los programadores. La asignación del montón no es determinista (es decir, no es difícil en tiempo real) y la fragmentación puede provocar situaciones inesperadas de falta de memoria a pesar de haber trabajado en las pruebas. La contabilidad que necesita el montón para realizar un seguimiento del espacio libre y el tamaño variable puede ser un problema con objetos pequeños. Por lo general, es mejor usar la asignación de grupo (tanto en C como en C ++), pero esto puede ser anormal para los programadores de C ++ que solo usan el montón.
El polimorfismo de tiempo de ejecución y otras llamadas indirectas suelen ser un gran impacto en el rendimiento, el problema suele ser mayor porque el optimizador no puede ver a través de ellos más que la búsqueda y el salto reales a la dirección. Las llamadas indirectas se deben evitar por esta razón en C y C ++, donde, como en C ++, están más arraigadas en la cultura (y son bastante útiles en otros dominios).
La interfaz implícita con clib puede ser problemática. Puede ser contradictorio que los problemas de clib se encuentren en la categoría C ++, pero el problema surge de la compartición implícita de recursos en entornos concurrentes (la compartición es más explícita en C). El uso de la implementación común de newLib a menudo arrastra una gran cantidad de hinchazón que generalmente no es necesaria en uC, por otro lado, newLibNanno no es reentrante, por lo que el acceso a él debe ser serializado (simplificando demasiado aquí). Este también es un problema para C, pero el acceso es más explícito. Como regla general, uno esencialmente no debe usar nada del espacio de nombres estándar en el contexto ISR a menos que esté seguro de que de alguna manera no accede al estado en clib (errorno o el montón, por ejemplo). También es importante si está utilizando subprocesos (prefiero RTC) para anular nuevos y eliminar para sincronizar el acceso a malloc y gratis.
En conclusión, C ++ tiene algunos problemas, pero esencialmente todos son reparables o evitables.
Ahora para C, aquí el problema es de orden superior. No tengo la capacidad sintáctica en C para abstraer cosas de una manera que pueda realizar la optimización o verificar invariantes en tiempo de compilación. Por lo tanto, no puedo encapsular adecuadamente las cosas de una manera que el usuario no necesite saber cómo funcionan para usarlas y la mayoría de mi detección de errores se realiza en tiempo de ejecución (que no solo es demasiado tarde sino que también agrega costos). Esencialmente, la única forma de ser genérico en C es a través de los datos, paso una cadena de formato a printf o scanf que se evalúa en tiempo de ejecución, por ejemplo. Entonces es bastante difícil para el compilador demostrar que no estoy usando algunas de las opciones que son teóricamente posibles cuando se pasan los datos correctos, lo que significa la posible generación de código muerto y la pérdida del potencial de optimización.
Sé que puedo estar desatando una tormenta de mierda aquí, pero mi experiencia en microcontroladores de 32 bits es que en una comparación de manzanas a manzanas de C y C ++, ambas escritas por expertos (como en C ++ potencialmente muy tentado) C ++ es el lenguaje mucho más eficiente tan pronto como cualquier cosa debe ser genérica (como en cualquier biblioteca) y son esencialmente equivalentes en casos no genéricos. También es más fácil para un novato aprovechar la experiencia de un implementador experto de bibliotecas en C ++.
Al mismo tiempo, hay realmente pocas funciones a las que no puedo pasar datos incorrectos, tan pronto como la entrada no es un int, pero
something
para el que estoy usando un int como método de representación, entonces existe la posibilidad de obtenerlo incorrecto (pase un valor no válido o un 'otroThing' en lugar de un 'algo'). En C, mi único método para verificar si el usuario se equivocó es en tiempo de ejecución. En C ++ tengo la capacidad de realizar algunas comprobaciones, no todas, pero algunas comprobaciones en tiempo de compilación que son gratuitas.Al final del día, un equipo C a menudo es tan poderoso como su programador más débil y el beneficio del código resultante tiene un multijugador de 1 o una penalización de rendimiento. Lo que quiero decir con esto es que es de alto rendimiento para un solo trabajo único en un entorno único de decisiones de diseño únicas o es lo suficientemente genérico como para ser utilizado en múltiples entornos (otro microcontrolador, otra estrategia de administración de memoria, otra latencia vs. compensaciones de rendimiento, etc., etc.) pero tiene un costo de rendimiento inherente.
En C ++, los expertos pueden encapsular las cosas y usarlas en muchos entornos donde la generación de código de tiempo de compilación se adapta a la tarea específica y la verificación estática evita que los usuarios hagan cosas estúpidas a un costo cero. Aquí tenemos mucho menos intercambio entre ser genérico y ser rápido y, por lo tanto, desde un punto de vista de costo versus beneficio, el lenguaje más productivo, más seguro y más productivo.
Es una crítica válida que todavía hay una gran escasez de buenas bibliotecas de C ++ para embebido, esto puede llevar a decisiones pragmáticas para usar principalmente C en un compilador de C ++. Las decisiones de usar solo C en un proyecto están esencialmente motivadas ideológicamente, por necesidad de soporte heredado o por admitir que el equipo no es lo suficientemente disciplinado como para abstenerse de un conjunto muy selecto de cosas estúpidas que uno puede hacer en C ++ pero no en C y al mismo tiempo lo suficientemente disciplinado como para no hacer ninguna de las cosas estúpidas mucho más grandes de las que no se puede protegerse en C pero sí en C ++.
fuente
Mi experiencia: recién salido de la escuela bajo viejos programadores de Bell Labs; estado trabajando durante 3 años, 2 en proyectos de investigación de pregrado; adquisición de datos / control de procesos en VB.NET. Pasó 1,5 años trabajando en una aplicación de base de datos empresarial en VB6. Actualmente trabajando en un proyecto para PC integrado con 2 GB de almacenamiento, 512 MB de RAM, 500 MHz x86 CPU; varias aplicaciones que se ejecutan simultáneamente escritas en C ++ con un mecanismo IPC en el medio. Si soy joven
Mi opinión: creo que C ++ puede funcionar eficazmente dado el entorno que he escrito anteriormente . Es cierto que el rendimiento en tiempo real no es un requisito para la aplicación en la que estoy, y en algunas aplicaciones integradas, puede ser un problema. Pero aquí están las cosas que he aprendido:
C ++ es fundamentalmente diferente de C (es decir, no hay C / C ++). Si bien todo lo que es válido C es válido C ++, C ++ es un lenguaje muy diferente y uno necesita aprender a programar en C ++, no C, para usarlo efectivamente en cualquier situación. En C ++, debe programar orientado a objetos, no de procedimiento, y no un híbrido de los dos (grandes clases con muchas funciones). En general, debe enfocarse en hacer clases pequeñas con pocas funciones y componer todas las clases pequeñas juntas en una solución más grande. Uno de mis compañeros de trabajo me explicó que solía programar de manera procesal en objetos, lo cual es un gran desastre y es difícil de mantener. Cuando comencé a aplicar más técnicas orientadas a objetos, descubrí que la capacidad de mantenimiento / legibilidad de mi código aumentó.
C ++ proporciona características adicionales en forma de desarrollo orientado a objetos que pueden proporcionar una forma de simplificar el código para que sea más fácil de leer / mantener . Honestamente, no creo que haya mucho en el camino de una mejora en el rendimiento / eficiencia del espacio al hacer POO. Pero creo que OOP es una técnica que puede ayudar a dividir un problema complejo en muchas piezas pequeñas. Y eso es útil para las personas que trabajan en el código, un elemento de este proceso que no debe ignorarse.
Muchos argumentos contra C ++ tienen que ver principalmente con la asignación dinámica de memoria. C tiene este mismo problema también. Puede escribir una aplicación orientada a objetos sin usar memoria dinámica, aunque uno de los beneficios de usar objetos es que puede asignar estas cosas dinámicamente de una manera fácil. Al igual que en C, debe tener cuidado sobre cómo administrar los datos para reducir las pérdidas de memoria, pero la técnica RAII lo hace más simple en C ++ (haga que la memoria dinámica se destruya automáticamente al encapsularla en objetos). En algunas aplicaciones, donde cada ubicación de memoria cuenta, esto puede ser demasiado salvaje y lanudo para administrar.
EDITAR:
fuente
Sí, el problema con C ++ es la mayor huella del código.
En algunos sistemas, está contando bytes, y en ese caso tendrá que aceptar un costo de ejecución tan cercano a los límites de sus sistemas como un aumento en el costo de desarrollo de C.
Pero, incluso en C, para un sistema bien diseñado necesita mantener todo encapsulado. Los sistemas bien diseñados son difíciles, y C ++ les da a los programadores un lugar para un método de desarrollo muy estructurado y controlado. Hay un costo para aprender OOP, y si desea cambiarlo, lo acepta y, en muchos casos, la administración preferiría continuar con C y no pagar el costo, ya que es difícil medir los resultados de un cambio que aumenta la productividad Puede ver un artículo del gurú de los sistemas integrados Jack Ganssle aquí .
La gestión dinámica de la memoria es el demonio. En realidad no, el demonio es el enrutamiento automático, la administración dinámica de memoria funciona muy bien en una PC, pero puede esperar reiniciar una PC al menos cada pocas semanas. Descubrirá que a medida que un sistema embebido continúa funcionando durante 5 años, la gestión dinámica de la memoria puede realmente estropearse y comenzar a fallar. Ganssle discute cosas como apilar y apilar en su artículo.
Hay algunas cosas en C ++ que son más propensas a causar problemas y utilizan muchos recursos, por lo que eliminar la administración dinámica de la memoria y las plantillas son pasos importantes para mantener la huella de C ++ más cerca de la huella de C. Esto sigue siendo C ++, no necesita dinámica gestión de memoria o plantillas para escribir bien C ++. No me di cuenta de que eliminaron las excepciones, considero que las excepciones son una parte importante de mi código que elimino en el lanzamiento, pero uso hasta ese momento. En las pruebas de campo, puedo hacer que las excepciones generen mensajes para informarme de que se ha detectado una excepción.
fuente
Pensé que este discurso anti-C ++ de Linus Torvalds era interesante.
No está hablando del mundo de los sistemas integrados, sino del desarrollo del kernel de Linux. Para mí, la relevancia proviene de esto: C ++ requiere comprender un contexto más amplio, y puedo aprender a usar un conjunto de plantillas de objetos, no confío en mí mismo para recordarlas cuando tenga que actualizar el código en unos pocos meses.
(Por otro lado, actualmente estoy trabajando en un dispositivo integrado que usa Python (no C ++, pero usa el mismo paradigma OOP) que tendrá exactamente ese problema. En mi defensa, es un sistema integrado lo suficientemente potente como para ser llamado PC Hace 10 años.)
fuente
Creo que otras respuestas hicieron un buen caso para los pros y los contras y los factores de decisión, por lo que me gustaría resumir y agregar algunos comentarios.
Para microcontroladores pequeños (8 bits), de ninguna manera. Solo estás pidiendo que te hagas daño, no hay ganancia y renunciarás a demasiados recursos.
Para microcontroladores de alta gama (por ejemplo, 32 bits, 10 o 100 MB de RAM para almacenamiento y RAM) que tienen un sistema operativo decente, está perfectamente bien y, me atrevería a decir, incluso recomendado.
Entonces la pregunta es: ¿dónde está el límite?
No estoy seguro, pero una vez que desarrollé un sistema para una uC de 16 bits con 1 MB de RAM y 1 MB de almacenamiento en C ++, solo para lamentarlo más tarde. Sí, funcionó, pero el trabajo extra que tenía no valía la pena. Tenía que ajustarlo, asegurarme de que cosas como las excepciones no produjeran fugas (el soporte OS + RTL era bastante defectuoso y poco confiable). Además, una aplicación OO generalmente realiza muchas asignaciones pequeñas, y la sobrecarga del montón para esas fue otra pesadilla.
Dada esa experiencia, asumiría para proyectos futuros que elegiré C ++ solo en sistemas de al menos 16 bits y con al menos 16 MB para RAM y almacenamiento. Ese es un límite arbitrario, y probablemente variará de acuerdo con el tipo de aplicación, estilos de codificación y modismos, etc. Pero dadas las advertencias, recomendaría un enfoque similar.
fuente
Hay algunas características de C ++ que son útiles en sistemas embebidos. Hay otros, como excepciones, que pueden ser costosos y cuyos costos pueden no ser siempre aparentes.
Si tuviera mis habilidades, habría un lenguaje popular que combinaría lo mejor de ambos mundos e incluiría algunas características que faltan en ambos idiomas; Algunos proveedores incluyen algunas de estas características, pero no hay estándares. Algunas cosas que me gustaría ver:
Sé que el padre de C ++ no está demasiado interesado en una versión de C ++ solo incrustada, pero creo que podría ofrecer algunas mejoras considerables con solo usar C.
¿Alguien sabe si se está considerando algo como lo anterior para algún tipo de estándar?
fuente
C ++ es más que un lenguaje de programación:
a) Es un "mejor" C b) Es un lenguaje orientado a objetos c) Es un lenguaje que nos permite escribir programas genéricos
Aunque todas estas características se pueden usar por separado, los mejores resultados se logran cuando las tres se usan al mismo tiempo. No obstante, si elige elegir solo uno de ellos, la calidad del software incorporado aumentará.
a) Es una "mejor" C
C ++ es un lenguaje tipado fuerte; más fuerte que C. Sus programas se beneficiarán de esta función.
Algunas personas tienen miedo de los punteros. C ++ incluye las referencias. Funciones sobrecargadas.
Y vale la pena decir: ninguna de estas características incurrió en programas más grandes o más lentos.
b) Es un lenguaje orientado a objetos.
Alguien dijo en esta publicación que abstraer la máquina en microcontroladores no es una buena idea. ¡Incorrecto! Todos nosotros, los ingenieros integrados, siempre hemos abstraído la máquina, solo con otro sintaxis que el de C ++. El problema que veo con este argumento es que algunos programadores no están acostumbrados a pensar en objetos, así no ven los beneficios de la POO.
Siempre que esté listo para usar el periférico de un microcontrolador, es probable que el periférico haya sido extraído para nosotros (de usted o de un tercero) en forma del controlador del dispositivo. Como dije antes, ese controlador usa la sintaxis C, como muestra el siguiente ejemplo (tomado directamente de un ejemplo NXP LPC1114):
/ * Configuración del temporizador para partido e interrupción en 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);
¿Ves la abstracción? Entonces, cuando se usa C ++ para el mismo propósito, la abstracción se lleva al siguiente nivel a través del mecanismo de abstracción y encapsulación de C ++, ¡a costo cero!
c) Es un lenguaje que nos permite escribir programas genéricos.
Los programas genéricos se logran mediante plantillas, y las plantillas tampoco tienen costos para nuestros programas.
Además, el polimorfismo estático se logra con plantillas.
Métodos virtuales, RTTI y excepciones.
Existe un compromiso cuando se utilizan métodos virtuales: mejor software frente a alguna penalización en el rendimiento. Sin embargo, recuerde que es probable que el enlace dinámico se implemente usando una tabla virtual (una matriz de punteros de función). He hecho lo mismo en C muchas veces (incluso de forma regular), por lo que no veo los inconvenientes en el uso de métodos virtuales. Además, los métodos virtuales en C ++ son más elegantes.
Finalmente, un consejo sobre RTTI y excepciones: NO LOS USE en sistemas embebidos. ¡Evítalos a toda costa!
fuente
Mi fondo, incrustado (mcu, pc, unix, otro), en tiempo real. Seguridad crítica. Introduje un empleador anterior a STL. Ya no hago eso.
Contenido de llama
¿C ++ es adecuado para sistemas integrados?
Meh C ++ es un dolor para escribir y un dolor para mantener. C + está bastante bien (no use algunas funciones)
C ++ en microcontroladores? RTOSes? Tostadoras? PC integradas?
De nuevo digo Meh. C + no es tan malo, pero ADA es menos doloroso (y eso realmente dice algo). Si tienes suerte como yo, puedes hacer Java incrustado. El acceso controlado a la matriz y la aritmética sin puntero hacen que el código sea muy confiable. Los recolectores de basura en Java incrustado no tienen la máxima prioridad, y hay memoria de alcance y reutilización de objetos, por lo que un código bien diseñado puede ejecutarse para siempre sin un GC.
¿OOP es útil en microcontroladores?
Seguro es. El UART es un objeto ..... El DMAC es un objeto ...
Las máquinas de estado de objetos son muy fáciles.
¿C ++ elimina el programador demasiado lejos del hardware para ser eficiente?
A menos que sea un PDP-11, C no es su CPU. C ++ era originalmente un preprocesador sobre C, por lo que Bjarne Stroustrup dejaría de reírse por tener simulaciones lentas de Simula mientras estaba en AT&T. C ++ no es tu CPU.
Ve a buscar un MCU que ejecute bytecodes de Java. Programa en Java. Ríete de los chicos de C.
¿Debería considerarse C ++ de Arduino (sin administración dinámica de memoria, plantillas, excepciones) como "C ++ real"?
No. al igual que todos los compiladores C bastardos que hay para MCU.
En cuarto lugar, Embedded Java o Embedded ADA están estandarizados (ish); todo lo demás es pena.
fuente
Los sistemas integrados están diseñados para realizar una tarea específica, en lugar de ser una computadora de uso general para múltiples tareas. Un sistema integrado es una combinación de hardware y software de computadora. C es la madre de todos los lenguajes modernos. Es un lenguaje completo de bajo nivel pero potente y ofrece todo tipo de hardware. Por lo tanto, C / C ++ es una opción óptima para desarrollar software para sistemas integrados, que es muy útil para todos los sistemas integrados. Como sabemos, C es un lenguaje en desarrollo. El sistema operativo UNIX está escrito en C. Debido a que el desarrollo exitoso de software consiste en seleccionar el mejor idioma para un proyecto determinado, es sorprendente descubrir que el lenguaje C / C ++ ha demostrado ser apropiado para procesadores de 8 y 64 bits. ; en sistemas con bytes, kilobytes y megabytes de memoria. C tiene el beneficio de la independencia del procesador, que permite a los programadores concentrarse en algoritmos y aplicaciones, en lugar de en los detalles de la arquitectura particular del procesador. Sin embargo, muchas de estas ventajas se aplican igualmente a otros lenguajes de alto nivel. ¿Pero C / C ++ tuvo éxito donde tantos otros lenguajes han fallado en gran medida?
fuente
<rant>
Creo que C ++ es un lenguaje malo en primer lugar. Si desea usar OOP, escriba programas Java. C ++ no hace nada para imponer paradigmas de OOP, ya que el acceso directo a la memoria está totalmente dentro de su poder para (ab) usarlo.
Si tiene una MCU, probablemente esté hablando de menos de 100kB de memoria flash. Desea programar en un lenguaje cuya abstracción de memoria es: cuando declaro una variable o una matriz, obtiene memoria, punto; malloc (también conocido como "nueva" palabra clave en C ++) debería estar más o menos prohibido su uso en software embebido, excepto quizás en raras ocasiones una llamada durante el inicio del programa.
Demonios, hay (con frecuencia) momentos en la programación incorporada en los que C no es lo suficientemente bajo, y necesita hacer cosas como asignar variables a los registros y escribir un ensamblaje en línea para ajustar sus rutinas de servicio de interrupción (ISR). Palabras clave como "volátil" se vuelven bastante importantes para entender. Pasa mucho tiempo manipulando la memoria a nivel de bits , no a nivel de objeto .
¿Por qué querría engañarse pensando que las cosas son más simples de lo que en realidad son?
</rant>
fuente