10

Actualmente estoy en el proceso de construir un sistema integrado, usando un procesador ARM Cortex M3, con 64 KB de SRAM. Por el momento, estoy buscando una manera de garantizar un rendimiento determinista con los contenedores STL, lo que incluye garantizar que no pueda terminar quedándome sin memoria en tiempo de ejecución.STL dentro del sistema integrado con memoria muy limitada

Me preocupa principalmente cómo los contenedores STL realizan la asignación dinámica de memoria. Aunque puedo utilizar un asignador personalizado para que estas estructuras obtengan memoria de un grupo que reservé, necesitaría configurar un grupo separado para cada estructura a fin de garantizar que una instancia de una estructura no ocupe el espacio de otra instancia.

Estoy trabajando con otras personas en este proyecto que no quieren preocuparse por la asignación de memoria sin procesar y preferirían poder utilizar las estructuras de datos "conocidas" (pila, cola, deque, etc.) . Por lo tanto, actualmente estoy considerando construir envoltorios alrededor de C-arrays para proporcionar estas estructuras. Esto permitiría la asignación estática de la memoria necesaria para admitir estos contenedores y permitir que los otros desarrolladores conozcan el tamaño del contenedor que han instanciado antes del tiempo de ejecución, según la información de tamaño de código proporcionada por el compilador. En mi opinión, esto garantiza que los problemas de interrupción de la memoria no pueden ocurrir en el tiempo de ejecución y simplifica considerablemente el diseño del sistema.

La otra opción implicaría la asignación de contenedores STL en la inicialización del sistema. Después del período de inicialización, no se puede asignar una memoria dinámica adicional. Sin embargo, que yo sepa, las estructuras de datos estándares STL de C++ no son compatibles con esto, requeriría que contenedores como una pila puedan ser preasignados (similar a un vector).

Agradecería cualquier comentario sobre mi propuesta para crear clases en torno a las C-arrays estándar? Además, ¿hay una forma más sencilla de asignar un contenedor STL de tamaño estático, como una pila o cola de tamaño estático, en tiempo de compilación? (Sé que esto es posible con el vector, pero los otros no estoy seguro)

Nota: He leído otra pregunta (Embedded C++ to use STL or not), pero el autor de esta pregunta no aclaró cuánta memoria tenía (aparte de cómo estaban usando un proceso ARM7) o parecen estar considerando una solución similar a la mía.

Segunda Nota: Soy consciente de que para algunos desarrolladores, 64 KB de SRAM pueden parecer una gran cantidad de memoria. De hecho, he hecho desarrollo en procesadores AVR con significativamente menos memoria, así que entiendo esta perspectiva. Sin embargo, desde mi vista actual (tal vez desinformada), 64 KB de memoria no es mucho cuando se habla de contenedores STL.

+1

Al final del día, fui con EASTL. Fue fácil de usar y funcionó bien. – BSchlinker

Respuesta

10

Esta pregunta es un poco confusa y extraña. Primero, aclaremos algunos conceptos erróneos.

Mencionas "stack, queue, deque" por nombre. Bueno, dos de estos no son contenedores . stack y queue son adaptadores de contenedor. Mira, en realidad no almacenan directamente los elementos; ellos simplemente median en la interfaz a ellos. stack asegura que solo puede presionar, abrir y obtener el elemento superior. queue asegura que solo puede retroceder, abrir frontalmente y obtener el elemento frontal (aunque también le permite obtener el elemento posterior).

Los adaptadores de contenedor realmente toman como uno de sus parámetros de plantilla el tipo de contenedor real que se va a utilizar. De modo que podría usar un stack con un std::list si lo desea. No necesariamente lo sugiero (dependiendo de su caso de uso), pero podría.

Los adaptadores de contenedor no se preocupan por la memoria; son los contenedores que usan que asignan memoria.

Si se está ejecutando en un sistema tan limitado de memoria, no encontrará que los contenedores estándar sean terriblemente amigables. Incluso si usa asignadores para darles almacenamientos intermedios de memoria de tamaño fijo, lo único que esos asignadores pueden hacer para evitar que el contenedor real asigne más memoria es lanzar una excepción.

Por ejemplo, si tiene un vector que tiene que trabajar dentro de 2 KB de memoria, si tiene un tamaño de 1 KB, y trata de asignar 2,5 kb más, el asignador puede no devuelva 2 KB. Puede devolver 2.5 KB según lo solicitado o lanzarstd::bad_alloc. Esas son sus únicas dos opciones. No hay forma de que el asignador le indique al vector que puede obtener más memoria de la que tiene, pero no tanto como quiere.

De forma similar, el asignador debe proporcionar nueva memoria, memoria recientemente asignada que se puede copiar. No se supone que proporcione el mismo punto de memoria solo con más cantidad disponible. Hacerlo probablemente cause problemas en algunas implementaciones.

Los asignadores están destinados a proporcionar diferentes regiones de memoria para el acceso; no están bien diseñados para limitar el tamaño del contenedor.

Mi sugerencia es rastrear a copy of EASTL. Está realmente diseñado para este tipo de cosas. El repositorio de Github al que te he vinculado tiene algunas correcciones de errores y demás, pero sigue siendo prácticamente el mismo. No es un mal código. Sus contenedores tipo STL proporcionan la mayor parte de la interfaz, por lo que pueden ser en su mayoría reemplazos directos. Pero proporcionan una funcionalidad especial para controlar específicamente las asignaciones de memoria.

+0

Gracias por el puntero a la fuente EASTL - No sabía que la fuente se había lanzado alguna vez. La última vez que revisé EASTL (hace mucho tiempo), parecía que solo el documento n2271 estaba disponible (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271. html). Espero tener algo de tiempo para ver la fuente publicada hasta ahora. –

+0

Este es quizás otro ejemplo de dónde me ha dolido cplusplus.com, ya que aprendí a asociar "Contenedores STL" con stack/queue/etc. de ellos (http://www.cplusplus.com/reference/stl/). Soy consciente de cómo una 'lista' podría ser utilizada como una pila, etc. (Tomé un curso de estructuras de datos donde tuve que construir estos adaptadores de contenedores). Estaba al tanto de EASTL, aunque parece haber cierta controversia al respecto en otras respuestas (vea la que he vinculado en mi pregunta original). – BSchlinker

+0

stack, queue, dequeue son estructuras de datos en el sentido genérico, que STL ha decidido implementarlas como adaptadores es simplemente un detalle de implementación. Entonces, no creo que haya ningún problema en particular en cómo el OP formuló su pregunta. ¡Aún consejos muy sólidos! – Ylisar

0

Además de EASTL, también puede usar static_vector de boost. Comparte la mayor parte de la API con std::vector y se puede usar con adaptadores de contenedor (cola, pila). En lugar de arrojar std::bad_alloc puede llamar al throw_bad_alloc(), por lo que se puede usar en un entorno incrustado sin excepciones.

Cuestiones relacionadas