2010-10-04 10 views
8

Sono un programmatore C++ e nel corso degli anni sono stati sottoposti a sentire la nozione che STL è non buon ambiente per l'utilizzo in ambienti embedded e quindi di solito vietati nell'uso per embedded basato projects.I credo che le librerie STL come Boost siano molto più potenti e forniscano uno strumento di sviluppo meno incline agli errori (in pratica la sintassi è poco intimidatoria, ma una volta passato penso che sia un vero tesoro). Inoltre, trovo le affermazioni che STL è pesante e aumenta l'impronta finale del codice assurdo perché poiché è templatizzato si otterrà solo il codice compilabile che ha richiesto e non l'intero STL.STL in ambiente di tipo embedded

La mia domanda è: quali sono le ragioni di questo questo populista (almeno la maggior parte fa capolino intorno a me la pensano così) nozione che richiede STL è non per enviornment incorporato?

Vedo una domanda di natura simile, ma qui mi aspetto un aiuto per evidenziare i pro e i contro in generale su STL e sull'ambiente embedded qui.

Edit: ecco io aggiungerò i punti come le risposte sono disponibili in:
1. Portabilità
2. far fronte a enormi allocazioni dymanice dai contenitori STL
3. STL è difficile eseguire il debug
4 Chiamate di funzioni profonde in STL si traducono in prestazioni ridotte per compilatori deboli con inlining (potenza dei funtori inutili!)

+0

Sono d'accordo con te sul punto relativo alla dimensione del codice generato.Ho trovato che il codice generato da STL è molto compatto, molto più piccolo del codice costruito a mano per tutti, ma esempi banali. – SingleNegationElimination

risposta

9

STL ha alcuni problemi con esso (come documentato da EASTL), su un sistema embedded o su un sistema su piccola scala, il problema principale è generalmente il modo in cui gestisce la (sua) memoria. un buon esempio di questo è stato il PSP port of Aquaria.

Il mio consiglio è però primo test, prima di seguire le ipotesi, se il test sono spettacoli vostra utilizzando semplicemente troppo cicli spazio/processori, allora forse un'ottimizzazione o due potrebbe spingerla nel regno della 'utilizzabile'.

Infine, il boost è basato sul modello, quindi se si guarda alle dimensioni del codice del modello generato, subirà lo stesso STL.

Edit/Update:

per chiarire la mia ultima dichiarazione (che è stato appena refering per aumentare VS STL). In C, è possibile (ab) utilizzare lo stesso codice per eseguire lo stesso lavoro su strutture diverse che condividono la stessa intestazione (o layout), ma con i modelli, ogni tipo potrebbe ottenere la propria copia (non ho mai testato se alcuni compilatori sono abbastanza intelligente da fare questo se 'ottimizzato per la dimensione' è enfatizzato), anche se è esattamente lo stesso (a livello di macchina/assemblaggio) come quello appena creato. boost ha il vantaggio di essere molto più pulito da leggere, e avere molte più cose in esso, ma ciò può portare a tempi di compilazione lunghi a causa di un ammontare copius di (molto grandi) intestazioni. STL guadagna perché puoi passare il tuo progetto in giro e non richiedere un download/accompagnamento di boost.

+0

@Necrolis Grazie per il link e la risposta! Tuttavia, non capisco "soffrire la stessa cosa di STL", voglio dire (Boost e STL) genera solo il codice richiesto, quindi è una buona cosa, intendevi "comportarti" invece di "soffrire"? –

+0

+1 per il collegamento a EASTL. Ma mi chiedo quanto è cambiato l'STL da allora – hirschhornsalz

+0

@drhirsch: l'implementazione potrebbe essere cambiata, ma la gestione della memoria non ha per i compilatori che conosco; cioè la memoria presa per i contenitori STL non viene rilasciata e altri potrebbero essere afferrati per quello che desideri. Nell'ambiente con memoria limitata può essere fastidioso. –

1

Molti pensano che (per molti motivi, come la portabilità) il C++ non sia adatto per un ambiente embedded. Esistono molti tipi di ambienti embedded e STL è certamente OK per alcuni di essi.

In generale, "più potente" è sempre una frase da temere quando è necessario scegliere qualsiasi cosa per un ambiente con risorse limitate, poiché spesso si desidera qualcosa di meno potente e più controllabile. Soprattutto se "più potente" significa che lo sviluppatore (o chiunque mantenga il codice in un secondo momento) avrebbe meno comprensione dell'implementazione sottostante.

2

Penso che la scelta dipenda dalla/e piattaforma/e targetizzata/e. Se hai un compilatore C++ corretto e non ti interessa la memoria allocata dinamica se usi contenitori, non vedo alcun problema.

8

Dipende da cosa intendi per embedded. Sui sistemi Atmel8, c'è un ram molto piccolo. Così piccolo che non puoi avere un malloc ragionevole. In questo caso, si desidera gestire la memoria in modo molto esplicito, probabilmente con array statici del tipo necessario. Se hai questo, in pratica non hai bisogno della maggior parte del STL.

Su sistemi a braccio, hai un sacco di ram. Usa STL!

+3

+1 per sottolineare che "embedded" copre una vasta gamma di sistemi da microcontrollori piccoli con poche centinaia * byte * di RAM fino ai sistemi di fascia alta con molti * GB * di RAM - come regola generale STL può essere appropriato per sistemi embedded di fascia medio-alta e probabilmente non per sistemi di fascia bassa. –

+2

Non ci vuole * molto * ram per avere buoni risultati con le raccolte dinamiche. Probabilmente è possibile utilizzare 10 kbyte. – SingleNegationElimination

3

mi sono imbattuto in questa presentazione: Standard C++ for Embedded Systems Programming

la maggior parte della complessità con i modelli è con il compilatore che nel sistema di runtime e che in parte è dove sta il problema - come non sappiamo per certo quanto di un'ottimizzazione che il compilatore è in grado di realizzare. In effetti il ​​codice C++ basato su STL dovrebbe essere più compatto e più veloce del codice C++ che non usa i template e nemmeno il codice C!

+0

+1 per le ottimizzazioni, potrebbe valere la pena ricordare che la libreria/binario risultante potrebbe essere più grande, ancora una volta, è necessario misurare. –

0

Per me, solo una buona ragione, non utilizzare alcuna libreria se non si adatta a vincoli limitati o la sua dimensione può essere un problema in seguito. Se questo non è un problema per te, fallo. In ogni caso non puoi migliorare.

0

Non ho riscontrato alcun inconveniente nell'utilizzo dell'STL nei sistemi incorporati e ho intenzione di utilizzarlo nel mio progetto corrente. Aumenta pure.

3

C'è qualche logica dietro la nozione che i modelli portano a un codice più grande. L'idea di base è piuttosto semplice: ogni istanziazione di un modello produce codice essenzialmente separato. Questo è stato particolarmente problematico con i primi compilatori - dal momento che i modelli (in genere) devono essere inseriti nelle intestazioni, tutte le funzioni in un modello sono inline. Ciò significa che se hai (per esempio) vector<int> istanziato in 10 file diversi, tu (in teoria) hai 10 copie separate di ciascuna funzione membro che usi, una per ogni file in cui la usi.

qualsiasi compilatore ragionevolmente recente (meno di, diciamo, 10 anni) avranno una logica nel linker di fondere questi di nuovo insieme, in modo da istanziare vector<int> in tutto 10 i file si tradurrà in una sola copia di ogni funzione membro voi utilizzata in corso nel file eseguibile finale. Nel bene o nel male, tuttavia, una volta diventato "noto" che i modelli producono codice gonfiato, molte persone non hanno guardato di nuovo per vedere se è rimasto vero.

Un altro punto (che rimane vero) è che i modelli possono semplificare la creazione di codice piuttosto complesso. Se stai scrivendo le cose da solo in C, in genere sei fortemente motivato a utilizzare l'algoritmo, la raccolta, ecc. Più semplice che possa svolgere il lavoro - sufficientemente motivato che è probabile che tu controlli in dettagli come il numero massimo di oggetti che potresti incontrare per vedere se riesci a cavartela con qualcosa di veramente semplice. Un modello può rendere così facile usare una raccolta generica che non ti preoccupi di controllare cose del genere, quindi (per esempio) finisci con tutto il codice per costruire e mantenere un albero bilanciato, anche se sei solo memorizzando (diciamo) 10 elementi al massimo in modo che una semplice matrice con ricerche lineari salverebbe la memoria e di solito girasse più velocemente.

+1

Riguardo al "bloat": anche se meno sicuro, l'uso di 'void * 'significa che esiste una singola versione delle collezioni/funzioni mentre con template c'è almeno una istanza per tipo con cui viene creata un'istanza. Non mi preoccupo per la codifica del server, ma per l'ambiente con memoria limitata, potrebbe essere un problema. –

+1

In realtà, molti compilatori (anche MSVC++ per Win32, dove il bloat non è una grande preoccupazione) sono in grado di piegare più funzioni insieme, purché siano identiche binarie. 'std :: list ' e 'std :: list ' è probabile che condividano la maggior parte dei membri (se 'sizeof (int) == sizeof (float)' ovviamente). – MSalters

+0

@MSalters: Sì, come ho detto, quasi ogni compilatore C++ negli ultimi 10 anni può farlo. Se la memoria funziona, MS l'ha aggiunta in VC++ 5.0, circa 15 anni fa circa (potrebbe anche essere stato prima - la mia memoria dei tempi non è neanche lontanamente chiara). –

2

Come si è detto, esiste una vasta gamma di sistemi "incorporati". Darò il mio punto di vista, che si concentra su sistemi safety critical e hard real time.

La maggior parte delle linee guida per i sistemi di sicurezza critici semplicemente proibiscono l'utilizzo di allocazioni di memoria dinamica.È semplicemente molto più facile e sicuro progettare il programma se non si deve mai preoccuparsi di un mal funzionamento di malloc/new fallito. E per i sistemi a lunga esecuzione in cui può verificarsi la frammentazione dell'heap, non si può facilmente dimostrare che l'allocazione della memoria non avrà esito negativo, anche su un chip/sistema con grandi quantità di memoria (specialmente quando il dispositivo deve funzionare per anni senza riavviare).

In scenari in cui vi sono scadenze temporali serrate, le incertezze relative all'allocazione della memoria dinamica e all'istanziazione di oggetti complessi sono spesso troppo grandi per essere affrontate. Questo è il motivo per cui molti programmatori che lavorano in queste aree si attengono a C. Puoi guardare la fonte C e indovinare quanto tempo impiega un'operazione. Con C++, è più facile per un codice dall'aspetto semplice richiedere più tempo di quanto sembri. Coloro che usano C++ in tali sistemi tendono ad attenersi al semplice semplice codice di vaniglia. E il codice che di solito è veloce, ma a volte richiede molto tempo per essere eseguito è peggio di un codice che è più lento ma coerente.

Quello che ho fatto in progetti più grandi è isolare il tempo reale e le funzioni critiche dal resto. Le cose non critiche possono essere scritte usando strumenti standard come il STL. Va bene finché il sistema operativo non interferisce con le parti critiche. E se non posso garantire che non ci siano tali interazioni, allora non usare affatto gli strumenti.

2

Ero su un progetto embedded che utilizzava C++ e STL in un sistema molto limitato (memoria in una frazione di un megabyte, ARMv4 a bassa velocità). Per la maggior parte, STL era grandioso, ma c'erano parti che dovevamo saltare (per esempio, std :: map richiede 2-4k di codice per istanziazione [che è un grande numero relativo alla nostra dimensione ROM], e avevamo la nostra sostituzione personalizzata per std :: bitset [era forse ~ 1k ROM]). Ma std :: vector e std :: list sono stati molto utili, così come lo è stato con boost :: intrusive_ptr per il conteggio dei riferimenti (shared_ptr era troppo grande, circa 40 byte di RAM per oggetto!).

Uno svantaggio dell'utilizzo di STL è che non si ha alcun recupero degli errori quando le eccezioni sono disattivate (che erano per noi, poiché le eccezioni e RTTI non erano a buon mercato sul nostro compilatore). Ad esempio, se un'allocazione di memoria non è riuscito in qualche parte del codice in questa linea (std :: map oggetto):

my_map[5] = 66; 

wouldnt lo vedono e il codice sarebbe solo silenzio continuare ad andare avanti; è probabile che l'oggetto si trovi ora in uno stato non funzionante, ma non andrai in crash fino a molto più tardi.

Detto questo, abbiamo avuto un grande successo con C++ e STL. Come ha detto un altro poster, provalo sul tuo sistema e misura quali parti di STL funzionano. Come nota a margine, c'è una grande relazione tecnica sulle prestazioni C++ in generale che è una buona lettura: http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf

1

Dipende dalla natura del sistema incorporato.

Un sistema di questo tipo può avere alcuni kilobyte di RAM (o meno) oppure può contenere molti megabyte o addirittura gigabyte. Quindi i vincoli di memoria possono o meno essere un problema.

Se il sistema ha vincoli in tempo reale, alcune parti o usi di STL potrebbero non essere adatti ad alcune parti della vostra applicazione. Le classi contenitore si basano molto sull'allocazione dinamica della memoria, sulla riallocazione e sulla copia di oggetti, e questo è spesso altamente non deterministico, quindi quando viene utilizzato in un codice time-critical, non si ha modo di garantire il rispetto delle scadenze.

Ciò non significa che non sia possibile utilizzare STL, anche in applicazioni in tempo reale. Ma è necessario progettare il codice attentamente in modo che si sappia che alcune operazioni non deterministiche non si verificheranno durante un processo critico.