2010-10-04 11 views
8

Soy un programador de C++ y en los últimos años han sido sometidos a oír la noción de que STL es projects.I basada no buen ambiente para su uso en sistemas empotrados y por lo tanto normalmente prohibidas en el uso para dispositivos integrados cree que las bibliotecas STL como Boost son mucho más potentes y proporcionan un medio de desarrollo mucho más rápido & menos propenso a errores (por supuesto, la sintaxis es poco intimidante pero una vez que creo que es un verdadero tesoro) .También me parece que STL es pesado y aumenta la huella final del código absurdo porque, dado que está templado, uno solo obtendrá el código compilable que solicitó y no el STL completo.STL en el entorno incorporado

Mi pregunta es ¿cuáles son las razones de esto esta populista (al menos la mayoría de los tíos más a mi alrededor creen que sí) noción que llama a STL es no para AMBIENTE incorporado?

veo una cuestión de naturaleza similar, pero aquí estoy esperando ayuda en señalar los pros y los contras en general acerca de STL y AMBIENTE incrustado aquí.

Editar: así que aquí voy a sumar los puntos y las respuestas vienen en:
1. Portabilidad Problemas
2. hacer frente a enormes asignaciones dymanice por contenedores STL
3. STL es difícil de depurar
4 Llamadas de función profunda en resultados de STL en bajo rendimiento para compiladores débiles con inlining (¡el poder de los funtores es inútil!)

+0

Estoy de acuerdo con usted en el punto sobre el tamaño del código generado.Descubrí que el código generado por STL es muy compacto, mucho más pequeño que el código creado a mano para todos los ejemplos menos triviales. – SingleNegationElimination

Respuesta

9

STL tiene bastantes problemas con esto (como se documenta aquí en EASTL), en un sistema integrado, o en un sistema de pequeña escala, el principal problema es generalmente la forma en que administra su memoria. un buen ejemplo de esto fue el PSP port of Aquaria.

Mi primer consejo es primera prueba, antes de seguir las suposiciones, si la prueba muestra que usa demasiados ciclos de espacio/procesador, entonces tal vez una optimización o dos podrían empujarlo al dominio de 'utilizable'.

Por último, es impulso basa plantilla, así que si lo que buscas en el tamaño del código de la plantilla generada, que va a sufrir el mismo que el STL.

Editar/actualización:

para aclarar mi última declaración (que se acaba de refiriendo a impulsar VS STL). En C, puede (ab) usar el mismo código para hacer el mismo trabajo en diferentes estructuras que comparten el mismo encabezado (o diseño), pero con plantillas, cada tipo puede obtener su propia copia (nunca he probado si hay compiladores). lo suficientemente inteligente como para hacer esto si 'optimize for size' está incluido), a pesar de que es exactamente lo mismo (en una máquina/nivel de ensamblaje) que uno que acaba de ser generado. boost tiene la ventaja de ser mucho más limpio para leer y tener muchas más cosas dentro de él, pero eso puede llevar a largos tiempos de compilación debido a una cantidad copusa de encabezados (a veces enormes). STL gana porque puede pasar su proyecto y no requerir una descarga/acompañamiento de impulso.

+0

@ Necrolis ¡Gracias por el enlace y la respuesta! Sin embargo, no entiendo "sufro lo mismo que STL", me refiero a que (Boost y STL) genera solo el código que se necesita, así que está bien, ¿quiso decir "comportarse" en lugar de "sufrir"? –

+0

+1 para el enlace a EASTL. Pero me pregunto cuánto ha cambiado el STL desde entonces – hirschhornsalz

+0

@drhirsch: la implementación puede haber cambiado, pero la gestión de la memoria no tiene para los compiladores que conozco; es decir, la memoria capturada para los contenedores STL no se lanza y se puede obtener más de lo que le gustaría. En un entorno con memoria limitada, puede ser molesto. –

1

Muchos piensan que (por muchas razones, como la portabilidad) C++ no es una buena opción para un entorno incrustado. Hay muchos tipos de entornos integrados y STL ciertamente está bien para algunos de ellos.

En general, 'más potente' es siempre una frase que temer cuando tiene que elegir algo para un entorno de recursos limitados, ya que a menudo quiere algo menos potente y más controlable. Especialmente si "más poderoso" significa que el desarrollador (o quienquiera que mantenga el código más adelante) tendría una comprensión menor de la implementación subyacente.

2

Creo que la elección depende de su (s) plataforma (s) de destino. Si tiene un compilador de C++ correcto y no le importa la memoria dinámica asignada si usa contenedores, no veo ningún problema.

8

Eso depende de lo que quiere decir con incrustado. En los sistemas Atmel8, hay muy poco ram. Tan poco que no puedes tener un Malloc razonable. En este caso, desea administrar la memoria de forma muy explícita, probablemente con matrices estáticas del tipo que necesita. Si tienes eso, básicamente no tienes necesidad de la mayor parte del STL.

En los sistemas de brazo, tienes suficiente carnero. Use STL!

+3

+1 para señalar que "incrustado" cubre una amplia gama de sistemas, desde pequeños microcontroladores con algunos cientos * bytes * de RAM hasta sistemas de gama alta con muchos * GB * de RAM - como regla general STL puede ser apropiado para sistemas embebidos de medios a altos y probablemente no para sistemas de gama baja. –

+2

No se necesita * mucho * RAM para obtener buenos resultados con colecciones dinámicas. 10 kbytes es probablemente utilizable. – SingleNegationElimination

3

me encontré con esta presentación: Standard C++ for Embedded Systems Programming

la mayor parte de la complejidad con plantillas es con el compilador que en el sistema de ejecución y que en parte es donde radica el problema - ya que no sabemos con certeza qué parte de una optimización que el compilador puede lograr. De hecho, se supone que el código C++ basado en STL es más compacto y rápido que el código C++ que no usa plantillas e incluso el código C.

+0

+1 para las optimizaciones, aunque vale la pena mencionar que la biblioteca/binario resultante podría ser más grande, una vez más, se necesita medir. –

0

Para mí, única buena razón, a no utilizar alguna biblioteca si no se ajusta a las restricciones limitadas o su tamaño puede ser un problema más adelante. Si eso no es problema para ti, ve por ello. En cualquier caso, no puedes ponerte mejor.

0

que no han experimentado ninguna desventaja de usar el TEL en sistemas embebidos y planeo usarlo en mi proyecto actual. Impulso también.

3

hay cierta lógica detrás de la idea de que las plantillas de plomo al código más grande. La idea básica es bastante simple: cada instanciación de una plantilla produce un código esencialmente separado. Esto fue particularmente problemático con los primeros compiladores, ya que las plantillas (normalmente) deben colocarse en los encabezados, todas las funciones en una plantilla son inline. Eso significa que si tiene (por ejemplo) vector<int> instanciado en 10 archivos diferentes, usted (teóricamente) tiene 10 copias separadas de cada función miembro que utiliza, una para cada archivo en el que la usa.

Cualquier compilador razonablemente reciente (menos de, por ejemplo, 10 años) tendrá algo de lógica en el enlazador para fusionarlos, por lo que crear instancias de vector<int> en 10 archivos solo dará como resultado una copia de cada función de miembro que utilizó en el ejecutable final. Para bien o para mal, sin embargo, una vez que se hizo "conocido" que las plantillas producen código inflado, mucha gente no ha vuelto a mirar para ver si seguía siendo cierto.

Otro punto (que sigue siendo cierto) es que las plantillas pueden hacer que sea fácil crear un código bastante compleja. Si escribe cosas por su cuenta en C, generalmente está muy motivado para usar el algoritmo, la recopilación, etc. más sencillos que pueden hacer el trabajo, lo suficientemente motivados como para verificar detalles como el número máximo. de artículos que pueda encontrar para ver si puede salirse con la suya con algo realmente simple. Una plantilla puede hacer que sea tan fácil usar una colección de propósito general que no se moleste en verificar cosas como esas, por lo que (por ejemplo) termina con todo el código para construir y mantener un árbol equilibrado, aunque solo esté almacenar (decir) 10 elementos como máximo para que una matriz simple con búsquedas lineales pueda ahorrar memoria y, por lo general, también funcionar más rápido.

+1

En cuanto a la "hinchazón": aunque menos seguro, el uso de 'void *' significa que existe una única versión de las colecciones/funciones, mientras que con la plantilla hay al menos una instanciación por tipo con la que se crea una instancia. No me preocupo por la codificación del servidor, pero para el entorno de memoria limitada, podría ser una molestia. –

+1

En realidad, muchos compiladores (incluso MSVC++ para Win32, donde la hinchazón no es una gran preocupación) pueden plegar varias funciones juntas, siempre que sean binarias idénticas. 'std :: list ' y 'std :: list ' es probable que compartan la mayoría de los miembros (si 'sizeof (int) == sizeof (float)' por supuesto). – MSalters

+0

@MSalters: Sí, como dije, casi todos los compiladores de C++ de los últimos 10 años pueden hacerlo. Si la memoria sirve, MS lo agregó en VC++ 5.0, hace unos 15 años aproximadamente (podría haber sido incluso antes, mi memoria del tiempo ya no está ni siquiera cerca de ser clara). –

2

como la gente ha dicho que hay una amplia gama de sistemas "integrados". Daré mi punto de vista, que se centra en los sistemas críticos de seguridad y en tiempo real.

mayoría de las directrices para los sistemas críticos de seguridad simplemente prohíben el uso de las asignaciones de memoria dinámica.Simplemente, es mucho más fácil y seguro diseñar el programa si nunca tiene que preocuparse de que falle una llamada malloc/new. Y para los sistemas de larga ejecución donde puede producirse la fragmentación del montón, no se puede demostrar fácilmente que la asignación de memoria no fallará, incluso en un chip/sistema con grandes cantidades de memoria (especialmente cuando el dispositivo debe funcionar durante años sin reiniciarse).

En los escenarios donde hay plazos de tiempo ajustados, las incertidumbres involucradas en la asignación de memoria dinámica y la creación de instancias de objetos complejos con frecuencia son demasiado grandes para manejarlas. Esta es la razón por la cual muchos programadores que trabajan en estas áreas se quedan con C. Puedes ver la fuente C y adivinar cuánto tiempo lleva una operación. Con C++, es más fácil que el código de apariencia simple tarde más de lo que parece. Aquellos que usan C++ en tales sistemas tienden a adherirse al simple código simple de Vanilla. Y el código que generalmente es rápido, pero ocasionalmente lleva mucho tiempo ejecutarlo, es peor que el código que es más lento pero consistente.

Lo que he hecho en proyectos más grandes es aislar el tiempo real y las funciones críticas del resto. Las cosas no críticas se pueden escribir usando herramientas estándar como STL. Eso está bien, siempre y cuando el sistema operativo no se interponga en el camino de las partes críticas. Y si no puedo garantizar que no haya tales interacciones, entonces no use las herramientas en absoluto.

2

Estaba en un proyecto incrustado que usaba C++ y STL en un sistema muy limitado (memoria en una fracción de megabyte, ARMv4 a baja velocidad). En su mayor parte, STL fue excelente, pero hubo partes que tuvimos que omitir (por ejemplo, std :: map requirió 2-4k de código por instanciación [que es un número grande en relación con nuestro tamaño de ROM], y tuvimos nuestro propio reemplazo personalizado para std :: bitset [era quizás ~ 1k ROM]). Pero, std :: vector y std :: list fueron muy útiles, al igual que el uso de boost :: intrusive_ptr para el recuento de referencias (shared_ptr era demasiado grande, ¡aproximadamente 40 bytes de RAM por objeto!).

La única desventaja de usar STL es que no tiene ningún error de recuperación cuando las excepciones están desactivadas (que eran para nosotros, ya que las excepciones y RTTI no eran baratos en nuestro compilador). Por ejemplo, si una asignación de memoria fallaron en alguna parte del código en esta línea (std :: mapa del objeto):

my_map[5] = 66; 

te podría verlo y el código no sería más silenciosa seguir adelante; es probable que el objeto esté ahora en un estado roto, pero no se bloqueará hasta mucho más tarde.

Dicho esto, tuvimos un gran éxito con C++ y STL. Como dijo otro cartel, pruébelo en su sistema y mida qué partes de STL funcionan. Como nota al margen, hay un gran informe técnico sobre el rendimiento de C++ en general que es una buena lectura: http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf

1

Depende de la naturaleza del sistema integrado.

Tal sistema puede tener algunos kilobytes de RAM (o menos), o puede tener muchos megabytes o incluso gigabytes. Entonces las restricciones de memoria pueden o no ser un problema.

Si el sistema tiene restricciones en tiempo real, algunas partes o usos de STL pueden no ser adecuados para algunas partes de su aplicación. Las clases de contenedor dependen en gran medida de la asignación dinámica de memoria, la reasignación y la copia de objetos, y esto con frecuencia es altamente no determinista, por lo que cuando se utiliza en código de tiempo crítico, no hay manera de garantizar el cumplimiento de las fechas límite.

Eso no quiere decir que STL no se puede usar, incluso en aplicaciones en tiempo real. Pero debe diseñar el código con cuidado para que sepa que no ocurrirá alguna operación no determinista durante un proceso de tiempo crítico.