10

Attualmente sono in fase di costruzione di un sistema embedded, utilizzando un processore ARM Cortex M3, con 64 KB di SRAM. Al momento, sto cercando un modo per garantire prestazioni deterministiche con i contenitori STL, che include l'assicurazione che non riesco a finire a corto di memoria in fase di esecuzione.STL all'interno del sistema embedded con memoria molto limitata

Sono principalmente interessato a come i contenitori STL eseguono l'allocazione dinamica della memoria. Sebbene io possa utilizzare un allocatore personalizzato per far sì che queste strutture recuperino memoria da un pool che ho messo da parte, avrei bisogno di configurare un pool separato per ogni struttura per garantire che un'istanza di una struttura non possa occupare lo spazio di un'altra istanza.

Sto lavorando con altre persone su questo progetto che non vogliono occuparsi dell'allocazione grezza della memoria e preferirebbero essere in grado di utilizzare le strutture di dati "ben note" (stack, coda, deque, ecc.) . Pertanto, attualmente sto prendendo in considerazione la costruzione di wrapper attorno ai C-array per fornire queste strutture. Ciò consentirebbe l'allocazione statica della memoria necessaria per supportare questi contenitori e consentire agli altri sviluppatori di conoscere la dimensione del contenitore che hanno istanziato prima del tempo di esecuzione, in base alle informazioni sulla dimensione del codice fornite dal compilatore. A mio parere, questo garantisce che non si verifichino problemi di interruzione della memoria in fase di runtime e semplifica notevolmente la progettazione del sistema.

L'altra opzione implica l'assegnazione di contenitori STL all'inizializzazione del sistema. Dopo il periodo di inizializzazione, non potrebbe verificarsi alcuna allocazione dinamica di memoria aggiuntiva. Tuttavia, per quanto ne so, le strutture di dati standard di C++ STL non supportano questo: richiederebbe che contenitori come uno stack possano essere pre-allocati (simile a un vettore).

Gradirei commenti sulla mia proposta di creare classi attorno agli array C standard? Inoltre, esiste un modo più semplice per allocare un container STL di dimensioni statiche, come una pila o una coda di dimensioni statiche, al momento della compilazione? (So ​​che questo è possibile con il vettore, ma gli altri non ne sono sicuro)

Nota: ho letto un'altra domanda (Embedded C++ to use STL or not), ma l'autore di questa domanda non ha chiarito la quantità di memoria che hanno aveva (altro poi come stavano usando un processo ARM7) o sembra che stia considerando una soluzione simile alla mia.

Seconda nota: sono consapevole che per alcuni sviluppatori, 64 KB di SRAM possono sembrare un sacco di memoria. In effetti, ho fatto lo sviluppo su processori AVR con una memoria significativamente inferiore, quindi comprendo questa prospettiva. Tuttavia, dalla mia attuale vista (forse non informata), 64 KB di memoria non sono molti quando si parla di contenitori STL.

+1

Alla fine della giornata, sono andato con EASTL. Era facile da usare e funzionava bene. – BSchlinker

risposta

10

Questa domanda è un po 'confusa e strana. In primo luogo, chiariamo alcuni equivoci.

Si cita "stack, queue, deque" per nome. Bene, due di questi non sono contenitori. stack e queue sono adattatori contenitore. Vedi, in realtà non memorizzano direttamente gli elementi; semplicemente mediano l'interfaccia con loro. stack assicura che è possibile solo premere, inserire e ottenere l'elemento superiore. queue assicura che puoi solo eseguire il push-back, pop-front e ottenere l'elemento front (pensavo che ti consenta di ottenere l'elemento back).

Gli adattatori contenitore in realtà prendono come uno dei parametri del modello il tipo di contenitore effettivo da utilizzare. Quindi potresti usare un stack con un std::list se lo desideri. Non lo suggerirei necessariamente (a seconda del tuo caso d'uso), ma tu potresti.

Gli adattatori del contenitore non si preoccupano della memoria; sono i contenitori che sono utilizzano che alloca memoria.

Se stai utilizzando un sistema così limitato di memoria, non troverai i contenitori standard per essere terribilmente amichevole. Anche se si utilizzano gli allocatori per fornire buffer di memoria di dimensioni fisse, l'unica cosa che gli allocatori possono fare per impedire al contenitore effettivo di allocare più memoria è di generare un'eccezione.

Ad esempio, se si dispone di un vector che ha bisogno di lavorare all'interno di 2 KB della memoria, se si ha una dimensione di 1 KB, e tenta di allocare 2.5KB di più, l'allocatore non può semplicemente restituire 2KB. Può restituire 2.5KB come richiesto o throwstd::bad_alloc. Quelle sono le tue uniche due opzioni. Non c'è modo per l'allocatore di dire allo vector che può ottenere più memoria di quello che ha, ma non quanto vuole.

Analogamente, l'allocatore è necessario per fornire nuova memoria, memoria appena allocata che può essere copiata. Non dovrebbe fornire lo stesso spazio di memoria solo con più di esso disponibile. Ciò potrebbe causare problemi in alcune implementazioni.

Gli allocatori hanno lo scopo di fornire diverse aree di memoria per l'accesso; non sono ben progettati per limitare le dimensioni del contenitore stesso.

Il mio suggerimento è di rintracciare a copy of EASTL. È davvero progettato per questo genere di cose. Il repository Github a cui ti ho collegato ha alcune correzioni di bug e così via, ma è ancora per lo più lo stesso. Non è un briciolo di codice. I loro contenitori simili a STL forniscono la maggior parte dell'interfaccia, quindi possono essere sostituzioni per lo più drop-in. Ma forniscono funzionalità speciali per controllare specificamente le allocazioni di memoria.

+0

Grazie per il puntatore alla sorgente EASTL - Non sapevo che la fonte fosse mai stata rilasciata. L'ultima volta che ho esaminato EASTL (molto tempo fa), sembrava che fosse disponibile solo il documento n2271 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271. html). Spero di avere un po 'di tempo per guardare la fonte rilasciata finora. –

+0

Questo è forse un altro esempio di dove cplusplus.com mi ha ferito, come ho imparato ad associare "STL Containers" con stack/queue/etc. da loro (http://www.cplusplus.com/reference/stl/). Sono a conoscenza di come un 'elenco' potrebbe essere usato come una pila, ecc. (Ho preso un corso sulle strutture dati in cui ho dovuto costruire questi adattatori per container). Ero a conoscenza di EASTL - anche se sembra esserci un po 'di polemica riguardo ad esso in altre risposte (vedi quella a cui mi sono collegato nella mia domanda iniziale). – BSchlinker

+0

stack, code, dequeue sono strutture di dati in senso generico, che STL ha deciso di implementarle come adattatori è semplicemente un dettaglio di implementazione. Quindi non penso che ci sia qualcosa di particolarmente sbagliato nel modo in cui il PO ha formulato la sua domanda. Consiglio ancora molto solido! – Ylisar

0

Oltre EASTL, è anche possibile utilizzare static_vector da boost. Condivide la maggior parte dell'API con std::vector e può essere utilizzato con adattatori contenitore (coda, stack). Invece di lanciare std::bad_alloc può chiamare throw_bad_alloc(), quindi può essere utilizzato in un ambiente embedded anche senza eccezioni.

Problemi correlati