Go Down

Topic: Classe "SafeString" una valida alternativa alla pessima "String" ... (Read 3035 times) previous topic - next topic

gpb01

Più volte, su questo forum, abbiamo sconsigliato la classe "String" per i vari problemi che essa provoca.

Il commento di "SparkFun" sulla classe "String" è, più o meno, il segunete: "la classe String (con 'S' maiuscola) in Arduino utilizza una grande quantità di memoria e tende a causare svariati problemi su progetti si una certa dimensione. tale clsasse dovrebbe essere fortemente evitata nella scrittura di librerie".

Similmente "Adafruit" all'incirca così commenta: "Nella maggior parte degli utilizzi, molti altri piccoli oggetti String vengono temporaneamente utilizzati forzando la nuova allocazione delle stringhe in una nuova area dell'heap e lasciando un grosso buco dove si trovava quello precedente (frammentazione della memoria)."

Noi stessi abbiamo più volte segnalato agli utenti che utilizzavano la classe "String": "NON sei su un PC dove c'è un sistema operativo ed un "garbage collector", sei su una piccola MCU con solo 2KBytes di SRAM, dove devi fare tutto tu e dove usare la classe "String", a causa dell'allocazione e riallocazione dinamica della memoria, porta quasi sempre ... a grossi problemi e sicuri mal di testa !!!"

Sempre "Adafruit" da una chiara rappresentazione grafica del problema ...



... e suggersice, come alemno primo palliativo per evitare il crash, quello di usare il metodo String.reserve () che, se impedisce la frammentazione dell'heap, non fa nulla e non riduce l'utilizzo eccessivo della memoria.
Inoltre, anche se si evita la frammentazione del "heap", la continua creazione di oggetti "String" e la copia di stringhe all'interno di essi (e tra di loro), è cosa estremamente lenta.

Continua ....
Search is Your friend ... or I am Your enemy !

gpb01

Il suggerimento, sempre da noi dato agli utenti che utlizzavano la classe "String" è stato: "Impara ad usare le stringhe classiche del C ... ovvero semplici array di char terminati dal carattere null (0x00) e le funzioni che trovi nella libreria standard (... che, oltretutto, è automaticamente inclusa dal IDE) AVR libc ed, in particolare, quanto è in <string.h> ".

Sicuramente, se questa è la strada migliore, certamente NON è la più semplice, almeno per "i meno esperti", che espone il programma al grosso rischio di "corruzione" della memoria se ... l'utente sbaglia il dimensionamneto dei char array o se copia stringhe classiche in altre strighe classiche magari di dimensioni più piccole o se fa comunque operazioni sugli array usando un indice fuori del valore massimo, ecc. ecc. ... tutte cose che, ribadisco "i meno esperti", rischiano facilmente di fare.

In aiuto a tali "meno esperti" c'è oggi una nuova libreria, installabile dal "library manager" che è una valida alternativa alla classe "String" pur mantenendone tutte le semplificazioni ed è la "SafeString" ;D

La libreria "SafeString" è stata progettata dall'autore (tale Matthew Ford) per "i principianti" come sostituto sicuro, robusto e debuggable perl'utilizzo delle stringhe in Arduino!

La guida completa all'installazione (da library manager) ed all'uso di detta libreria, si trova QUI ... ne consiglio una attenta lettura.

Se ne è parlato anche parecchio nel gruppo di Google dedicato agli "sviluppatori di Arduinio", QUI, è la discussione ancora va avanti :)

SafeString è sicuramente una valida alternativa alla classe "String", offre le stesse facilitazioni, ma è estremamente sicura, evita i guai della "String" ed è ben manutenuta ... consiglio di provarla !  :smiley-mr-green:

Fatemi sapere ... ;)

Guglielmo

P.S.: io comunque continuo ad usare le funzioni classiche che si trovano in <string.h> ... ormai ho l'abitudine :D
Search is Your friend ... or I am Your enemy !

Standardoil

non so, non sono convinto...
non metto in dubbio la "sicurezza" della classe, che guarderò con calma

la questione è che così facendo ci si allontana dallo spirito del C

ho visto (e temo che con questa classe ne vedremo tanti altri) gente che usa una String solo per non fare due print in successione, manco gli viene in mente di farlo

e mettergli una ulteriore "stampella" non sono sicuro che gli insegni a "camminare"


EDIT
Ho dato una rapida occhiata a quella classe:  ma si basa sulla pre-dichiarazione della dimensione massima dell'oggetto?
e quindi dove sarebbe il suo vantaggio competitivo rispetto alla pre-esistente Pstring?
Non presurrò più la buona fede di chi:
NON indenta, USA la classe String o NON esegue le ricerche
E di chi non risponde alle domande Tante volte è stato segnalato che è sbagliato, quindi NON sono in buona fede
Non bado a studenti, che copino altrove

gpb01

e mettergli una ulteriore "stampella" non sono sicuro che gli insegni a "camminare"
Sicuramente, difatti per primo dico che la cosa migliore sarebbe imparare ad usare bene le funzioni di <string.h>, ma ...l'esperienza ormai ci insegna che, per una buona fetta di utenza, sono cose già troppo complicate che la classe "String" gli semplifica ... ecco, questa fornisce la stessa semplicità, con tutte le stesse facilitazioni (concatenazioni, confronti, ricerca di token, e tutto quello che è possibile fare con "String") nascondendogli l'uso delle funzioni di <string.h> che in realtà usa.

Guglielmo
Search is Your friend ... or I am Your enemy !

gpb01

Ah ... dimenticavo, se hai obiezioni, critiche, suggerimenti, domande e quant'altro ... ti prego di andare nell'apposito gruppo di "Arduino" e esponi il tutto li. :)

Questo thread è SOLO per informare l'utenza sull'esistenza di un'alternativa e per cercare si aiutare (nei limiti del possibile) chi avesse difficoltà nel suo uso, NON per discussioni sulla libreria stessa ... dato che l'autore NON fa neanche parte del forum e NON ci legge. ::)

Grazie.

Guglielmo
Search is Your friend ... or I am Your enemy !

docdoc

Grazie Guglielmo, ottima cosa!

Anche se sono anche io della "vecchia scuola" (ossia ho imparato prima il C, e solo dopo sono arrivati C++ et similia) per cui credo che userò comunque sempre il modo classico, potrebbe essere sicuramente utile non solo per i meno esperti di programmazione in generale, ma anche per chi proviene da ambienti come Java o C# i quali hanno l'abitudine a quella classe di oggetti più "facili da maneggiare".

PS: non capisco perché, ma all'autore non interessa stare anche in questo che è il forum ufficiale di Arduino?? Boh..
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

docdoc

Update: ho dato un'occhiata, ed in parte sono rimasto un poco deluso. La programmazione ad oggetti non avrebbe permesso di fare override della classe String, o anche crearne una apposita, analoga?

Magari alla prima occasione di provare ad usarla mi analizzerò meglio i sorgenti della SafeString e vista dall'interno forse mi dovrò ricredere, però, per dire, non capisco perché iniziare con dichiarazioni che attualmente sono del tipo:

createSafeString(stringOne, 35);

invece di quello che mi aspettavo di vedere, ossia o questo:

String stringOne(35);

oppure:

SafeString stringOne(35);

Insomma, si, tutto bello, bella la boiserie, ma non è che mi convinca appieno...

PS: si, so che c'è il Google Group dove ne parla anche lo stesso autore, ma intanto mi interessa l'opinione della "nostra" comunità che già conosco... ;)

PS2: Tra l'altro la libreria contenuta in uno spazio GitHub che non è gestito dall'autore ma da uno (?) che semplicemente gli "presta" lo spazio è un'altra cosa che non concepisco...
Ossia mi chiedo: "perché"? Lasciamo stare il fatto (anomalo) che uno che sviluppa una libreria per Arduino ma non frequenta il forum ufficiale di Arduino, mi chiedo perché non abbia voglia di usare gli strumenti comuni che usano milioni di sviluppatori, e quindi gestire da sé la sua libreria (incluse le pagine su GitHub come versioni, request, wiki, eccetera). E' timido? E' pigro? E' straniero?
Boh...
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

gpb01

Eh NO, è giusto che sia fatta come è fatta, proprio per NON usare in alcun modo la classe String e distinguersi da essa.

Considera che, se hai letto il gruppo, aveva chiesto di rimpiazzare la String con la SafeString, ma ... pare che la String NON si tocca e quindi ... nomi diversi dato che ciascuna deve restare indipendete dall'altra.

Per il resto, ripeto, "De gustibus non est disputandum" ... :)

Guglielmo
Search is Your friend ... or I am Your enemy !

Standardoil

Considera che, se hai letto il gruppo, aveva chiesto di rimpiazzare la String con la SafeString, ma ... pare che la String NON si tocca e quindi ... nomi diversi dato che ciascuna deve restare indipendete dall'altra.


Guglielmo
Beh   
Vorrei vedere

La classe String fa parte della libreria standard del linguaggio, non è che la si cambia facile...
Non presurrò più la buona fede di chi:
NON indenta, USA la classe String o NON esegue le ricerche
E di chi non risponde alle domande Tante volte è stato segnalato che è sbagliato, quindi NON sono in buona fede
Non bado a studenti, che copino altrove

docdoc

Eh NO, è giusto che sia fatta come è fatta, proprio per NON usare in alcun modo la classe String e distinguersi da essa.
Ma non si "usa" la classe String se fa override, e neanche si modifica la String ma semplicemente la "sua" classe facendo override sulla String, "nasconde" le corrispondenti funzioni, e solo per i progetti dove questa viene usata.
(voglio sperare che il core di Arduino internamente non usi le String... ;) )

Quote
Considera che, se hai letto il gruppo, aveva chiesto di rimpiazzare la String con la SafeString, ma ... pare che la String NON si tocca e quindi ... nomi diversi dato che ciascuna deve restare indipendete dall'altra.
Si, ma in ogni caso per me la soluzione migliore e più "pulita" era appunto di definire una classe "SafeString" ma rendendola visibile direttamente, e non tramite i "giochini" come mi pare faccia in quella libreria, e che costringono a fare dichiarazioni di variabili in quel modo "rozzo" :D

Vorrei vedere
La classe String fa parte della libreria standard del linguaggio, non è che la si cambia facile...
Ma chi ha parlato di cambiare la classe String della libreria? Fare una classe che la eredita e ne fa override delle parti che vanno cambiate per gestire diversamente l'allocazione non è "cambiare" nulla.
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

gpb01

La classe String fa parte della libreria standard del linguaggio, non è che la si cambia facile...
... in realtà, se andate a leggere, vedrete che era stato chiesto proprio di "riscrivere" la classe String seguendo quanto fatto nella SafeString  ;D  ... la richesta è stata declinata ...

Guglielmo
Search is Your friend ... or I am Your enemy !

maubarzi

La dichiarazione, da quel che scrivi, semplicemente mi pare segua l'implementazione del creational design pattern.
Disaccoppia la chiamata di creazione dall'oggetto creato.
Il metodo da te preferito è il costruttore dell'oggetto.
Entrambe le vie sono usate correntemente a seconda dei casi e a volte dei gusti, non ci vedo nulla di così strano o esotico.

Riguardo implementare una cosa nuova come override di una vecchia, la trovo, sinceramente, una porchieria.
Tanto vale fare la classe da zero, come scrivi sotto, e implementare una interfaccia simile senza però nessun vincolo, cioè senza l'uso di una vera interfaccia, ma giusto per mantenere la familiarità in chi la utilizza.

Per il resto, io avrei debellato sia String che evitato questa implementazione, creando un po' di cultura sull'uso delle stringe C standard.
A volte, si crede di semplificare la vita creando questi oggetti ma secondo me si semplificherebbe di più se non ci fossero, così la gente sarebbe costretta a imparare nel modo giusto fin da subito senza vedere delle false panacee.
Occhio non vede cuore non duole.
Parlo solo di Arduino ed MCU dove c'è il rischio concreto di frammentazione della memoria a causa di queste classi.
E ve lo dico io che al C mi ci sono avvicinato solo con Arduino e quindi abituato da sempre ad usare la classe String in altri linguaggi.
Qui, non ne sento minimamente la mancanza.
Anzi, a volte mi riscrivo anche funzioni io perchè quelle già pronte richiedono troppe risorse, es. sprintf, quindi usare gli array di char, a maggior ragione, non mi cambia la vita.

Maurizio
Nessuna buona azione resterà impunita!

Preistoria -> medioevo -> rinascimento -> risorgimento -> rincoglionimento!

nid69ita

... non capisco perché iniziare con dichiarazioni che attualmente sono del tipo:
createSafeString(stringOne, 35);
oppure:
SafeString stringOne(35);
Insomma, si, tutto bello, bella la boiserie, ma non è che mi convinca appieno...
Non capisco @docdoc, quella libreria usa un truccaccio (come hai scritto poi) con una macro per dichiarare un buffer fuori dalla dichiarazione dell'oggetto.     
Nella pagina github specifica che questo
  createSafeString(str, 40);
viene "espanso" in
  char str_SAFEBUFFER[40+1];
  SafeString str(sizeof(str_SAFEBUFFER),str_SAFEBUFFER,"","str");

Per me è un pò un accrocchio. Viola le regole di buona programmazione a oggetti.
Se non ricordo male esiste anche una libreria (forse tu @docdoc l'avevi segnalata) PString3  dove a cura del programmatore dichiarare a priori un buffer, cosa che questa lib fa con trucchetto della macro.

Però, in tutti casi abbiamo un array di dimensione fissa, non di certo la facilità d'uso (ma con i problemi di micro-frammentazione memoria) di una allocazione dinamica. Non capisco quanto possa aiutare un utente alla prime armi. Rimango scettico.
my name is IGOR, not AIGOR

maubarzi

Ok, mi rimangio quanto scritto sopra sul costruttore, un trucco e bistrucco non è certo un design pattern, e mi confermi ulteriormente la mia idea iniziale, che tanto vale usare gli array di char e debellare il resto.

Maurizio
Nessuna buona azione resterà impunita!

Preistoria -> medioevo -> rinascimento -> risorgimento -> rincoglionimento!

gpb01

... Non capisco quanto possa aiutare un utente alla prime armi. Rimango scettico.
... aiuta nel senso che l'utente "alle prime armi" è abituato ad usare i metodi "semplici" della classe String ... questa glie li fornisce senza usare le String e nascondendogli la complessità delle funzioni di <string.h> ... PUNTO.

Nessun utente "alle prime armi" va a vedere come è fatta dentro, la usa e basta, quindi lo aiuta ad evitare i casini della classe String pur mantenendo la ... semplicità d'uso.

Detto questo ribadisco quanto detto al post #4 ... quindi, andate a discutere della bontà o meno di essa nel gruppo di "Google" degli sviluppatori Arduino ... altri "commenti" sulla libreria verranno cancellati.

Guglielmo
Search is Your friend ... or I am Your enemy !

Go Up