Classe "SafeString" una valida alternativa alla pessima "String" ...

Maurizio il tuo discorso non fa una piega e lo trovo del tutto condivisibile.
Il fatto è che io non ritengo a priori "una strada sbagliata" usare la classe String, mentre lo è di sicuro usarla male.

E' come se io dicessi a qualcuno che il saldatore non te lo faccio usare perché è pericoloso.
Non è meglio insegnare ad usare qualcosa facendo le dovute raccomandazioni sui rischi che si possono incontrare e su come evitarli?

il socio si è dimostrato di nuovo mio "fratello di quaderno a quadretti", il suo ultimo intervento potrei averlo scritto io,

comunque usare la classe String senza un sistema operativo è la versione informatica della roulette russa

non è 'possibile' che succedano casini: è "sicuro"

l'unica parte incerta è "quando" succederanno

e non cominciamo con le storie che basta dichiarare l'oggetto String locale perchè le cose tornino a posto quando l'oggetto stesso "decade" alla fine della funzione

chi dice che sia vero? la classe string usa la gestione dinamica della memoria, tutte le considerazioni sul "tempo di vita" delle variabili sono aria fritta

e comunque, un programmatore che è in grado di fare di queste sottigliezze conosce abbastanza della programmazione per NON usare la classe String, e quindi mi fa, a me personalmente, il favore di non farlo con arduino, altrmenti lo metto nel nel cerchio Settimo, Terzo girone dell'Inferno: Bestemmiatori e 'String'oisti

Prima legge di Nelson (che sono io): fare cappelle solo perché non si vuole imparare a lavorare bene ti declassa agli occhi di chi invece bene ci lavora

cotestatnt:
... Il fatto è che io non ritengo a priori "una strada sbagliata" usare la classe String, mentre lo è di sicuro usarla male. ...

... il fatto è che la maggior parte di quelli che qui arrivano (oltre il 90%) sono utenti di MCU AVR, spessissimo di piccolo taglio ... ATmega328P e ... con soli 2 KB di SRAM, mettila come vuoi ... alla fine vai nei casini, quindi ... meglio prevenire e dirgli di non usarla (poi, se mai un giorno andranno a programmare su qualche cosa di più completo, magari con un OS che gestisce la memoria, allora vedranno che le cose cambiano :wink:).

Guglielmo

PS: mi sono sovrapposto al post di Standardoil ... :smiley:

Continuo a non essere d’accordo.

cotestatnt:
E’ come se io dicessi a qualcuno che il saldatore non te lo faccio usare perché è pericoloso.

In realtà, per fare un paragone corretto, si dovrebbe considerare un saldatore che dopo un certo tempo, dipendente dal lavoro che se ne deve fare, fa saldature fredde (cioè talmente bacate da non far contatto).
Ok, normalmente lo fa dopo ore, quindi se lo usi per piccoli lavoretti non incappi nel problema, ma perchè usare questo saldatore se con un piccolo costo aggiuntivo ne puoi avere uno che non avrà mai problemi?

Ecco, questo sarebbe un paragone un po’ più calzante.

Una classe che frammenta la memoria, non può essere usata bene o male. Se la usi ti tiri dietro il suo problema se non la usi no.

La questione è tutta qui.
Poi, tutti i linguaggi di alto livello usano una implementazione della classe String, ma li è tutta un’altra storia, c’è un gestore che si occupa di tenere la memoria in ordine e non si hanno risorse così limitate.

Personalmente ritengo che chi scrive librerie per Arduino usando la classe String, non pensa che le sue librerie possano venire usate in progetti che devono girare per molto tempo.
Altrimenti non userebbero certe bombe ad orologeria.

Poi, ognuno è libero di farsi del male come meglio crede, ma ritengo che sia un approccio culturalmente sbagliato.

Maurizio

P.S.

Standardoil:
il socio si è dimostrato di nuovo mio “fratello di quaderno a quadretti”, il suo ultimo intervento potrei averlo scritto io,

Socio, lo ammetto, ho copiato ;D

Ragazzi io non voglio insistere più di tanto, però qui mi sembra che ci sia un po' di talebanesimo nei confronti di questa povera classe quindi vedo di finirla prima di essere passato a fil di Kalashnikov (sto scherzando eh :wink: ;)).
Voi dite che frammenta la memoria a prescindere, io dico dipende e che sicuramente ci sono "pratiche da neofita" molto più dannose dell'utilizzo di String (abuso del delay, convertire 2/3 volte la stessa informazione, utilizzo eccessivo di variabili globali etc etc).

P.S.
Volevo solo aggiungere che io ho realizzato dei progetti dove se ne fa un uso appropriato (a mio modo di vedere) che girano H24 senza il minimo problema ormai da anni, sia su MCU Espressif, ma anche e soprattutto su dei "miseri" ATMega328.
A mio avviso, se un firmware crea problemi, la colpa non è del saldatore ma di chi lo usa.

Io non ho intenzione di passare nessun a fil di spada, per cui tranquillo.
Però il paragone con il saldatore, purtroppo non calza, perchè con il saldatore è ovvio che la colpa è sempre di chi lo usa...
Per il resto, quel che c'era da dire è stato detto sia da parte tua che da parte mia, per cui, non serve continuare ripetendo le stesse cose :wink:

Maurizio

Standardoil:
e non cominciamo con le storie che basta dichiarare l'oggetto String locale perchè le cose tornino a posto quando l'oggetto stesso "decade" alla fine della funzione

Chi lo dice prende un abbaglio grosso.
Quando un oggetto String viene dichiarato locale, l'oggetto è in memoria stack. Ma la classe String usa internamente malloc,free,realloc, quindi prende spazio in Heap, che l'oggetto sia locale o globale. Ovvero il suo membro puntatore a char buffer sempre punta a qualcosa in heap. Ed è quella che si frammenta.

cotestatnt:
Ragazzi io non voglio insistere più di tanto, però qui mi sembra che ci sia un po' di talebanesimo nei confronti di questa povera classe quindi vedo di finirla prima di essere passato a fil di Kalashnikov (sto scherzando eh :wink: ;)).
Voi dite che frammenta la memoria a prescindere,

Non a prescindere, è facile però avere un uso che frammenta la memoria. E l'utente medio non lo sa/capisce.

Vorrei rammentare a tutti un mio post della pagina precedente ...

gpb01:
...
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 .......

... quindi, magari ora finiamola qui con questa lunga (... se pur interessante) discussione. Grazie :wink:

Guglielmo

SafeString V2 is now out. See the updated tutorial

V2 adds wrapping of char * and char in SafeStrings for safe processing that updates the original c-string directly.
(please excuse my lack of Italian)

>drmpf: Hi, thanks a lot for the info ! :slight_smile:

E' disponibile l'aggiornamento alla V2 di SafeString V2. QUI il tutorial aggiornato.

La V2 aggiunge il wrapping di "char *" e "char []" in SafeStrings per trattamento corretto e sicuro che aggiorna direttamente la c-string originale.

Guglielmo

Karma+
thank you very much for the update!

V2.0.6 of the SafeString library includes a replacement for Arduino Serial Text I / O that works in real world applications.
A detailed tutorial is here

**Arduino Serial is not suitable for handling Text I / O in Real World applications. **

See the tutorial for the details
or this forum post for a summary

Thanks a lot for the info !

Guglielmo

Another Karma+!!!

SafeString V3 has been released.
It adds SafeStringReader a non-blocking replacement for Serial.readString (), with optional echo and non-blocking timeout
BufferedInput for when 64bytes is just not enough
SafeStringStream provides a means to stress test sketches the use Text I / O

The Text I / O for the Real World has been fully revised.

The Quick start is: -

  • Install the SafeString library (V3 +) from the Arduino Library Manager or the zip file
  • For text input use a SafeStringReader - a non-blocking robust high level reader for reading lines of data or general text with delimiters, with optional echo and optional non-blocking timeout
  • For text processing use the SafeString methods - what Arduino Strings was meant to be, but with out the memory problems and odd errors and with detailed error messages.
  • For text output write to a BufferedOutput - the non-blocking replacement for Serial print, so your debug msgs and results do not delay the rest of the loop and cause missed input.
  • For testing use a SafeStringStream - stress tests your sketch's text processing.
  • If you need a larger input buffer use a BufferedInput - for when the sketch processing delays the reading of the input and chars are lost

Still thanks for the info !!! :slight_smile:

Guglielmo

SafeString V4 has been released. This version more closely aligns method returns to those used by Arduino Strings. In particular, indexOf now returns an int and returns -1 if not found (like Arduino Strings).

Also I have a new tutorial, Taming Arduino Strings - How to avoid memory problems which shows that Arduino Strings are not that ‘bad’. The tutorial shows you how to avoid memory fragmentation and out-of-memory issues when using Arduino Strings

In particular it shows that using Arduino Strings on Uno and Meg2560 is virtually bullet proof, even if you run out of memory.
(See What happens when UNO runs out of heap memory )

GOOGLE TRANSLATION

SafeString V4 è stato rilasciato. Questa versione allinea più da vicino i ritorni di metodo a quelli utilizzati da Arduino Strings. In particolare, indexOf ora restituisce un int e restituisce -1 se non trovato (come Arduino Strings).

Inoltre ho un nuovo tutorial, Domare le stringhe Arduino - Come evitare problemi di memoria che mostra che le stringhe Arduino non sono così “cattive”. Il tutorial mostra come evitare la frammentazione della memoria e problemi di memoria insufficiente quando si utilizza Arduino Strings

In particolare mostra che l’utilizzo di Arduino Strings su Uno e Meg2560 è praticamente a prova di proiettile, anche se si esaurisce la memoria.
(Vedi Cosa succede quando UNO esaurisce la memoria heap)

Seguo. :wink:

Another Karma+!!!

An update:
After I finished writing SafeStrings, I was prompted to look at Arduino Strings more closely.
It turns out that by following a few guidelines you can successfully use Strings in your code.
On Uno and Mega2560 it turns out Strings are essentially bullet proof.
For other boards (with more memory) see the guide lines in my tutorial
Taming Arduino Strings

For the ESP32 / ESP8266 which uses Strings extensively in their Web support libraries, Taming Arduino Strings suggests a periodic automatic reboot and provides sample code to do that.
I am using that approach on a commercial project I am doing at the moment.

SafeStrings still has some advantages over Arduino Strings

Complete control over memory use

SafeStrings are a wrapper around a char that provides safety from buffer overruns and out of range indexing. Because SafeString uses a fixed char , the memory usage is fixed when you create the SafeString and does not change. When you create global SafeStrings their memory usage is reported by the compiler so it is simpler to see how much SRAM your code is using. SafeStrings also use less memory because they don't need to convert “text” to a SafeString before using it in compare and indexOf functions.

Catches, flags and ignores Errors and prints a detailed message to help you fix the error

SafeString checks every one of its function calls for null pointers, buffer-overrun and out of range indexing. Function calls the would cause an error are ignored, ie the SafeString remains unchanged, and the error is flagged and a detailed error messge displayed that allows you to pin point the problem and fix it. SafeString also does not have the errors that are in Arduino String's code

Simple non-blocking Serial Readers

The Arduino String reader, Serial.readStringUntil () can block the loop waiting while waiting for data. While you can code non-blocking readers using Strings, the methods in the SafeString are simpler and have a number of advanced functions like tokenizing the input, non-blocking input timeouts, selectable echo of the input and a skipToDelimiter function to skip over un- wanted or partial input. The SafeString readers also count the number of chars read so you can check when an entire web response has been received.

Better number parsing methods

As noted above, the String toInt () method can give odd results. The SafeString toInt (int i), toLong (long l) etc, return true if the string is a valid number and updates the argument, otherwise they return false. The String toInt () method just returns 0 if the string is not a number and returns 5 for "5.9" and for "5a"

Easier to use with libraries

Third party libraries often return their text results as a char *. If you use Strings, you will be making a complete copy of the text when you assign the result to a String, using extra memory. On the other hand with SafeString, you can just wrap the char * in a SafeString without taking a copy and then safely parse and process the data.

More text manipulation functions

While Strings have startsWith, endsWith, indexOf, lastIndexOf, substring, replace and remove methods, SafeString has all of those methods plus a full set of print () methods to print to a SafeString and prefix (), startsWithIgnoreCase (), indexOfCharFrom () , removeBefore (), removeFrom (), removeLast (), stoken (), nextToken () and non-blocking readFrom (), writeTo (), read (), readUntil (), readUntilToken ()

The SafeString library also has a SafeStringStream class that lets you automate the testing of sketches that expect to process Stream data input.

There are also BufferedInput and BufferedOutput classes that provide larger input buffers and non-blocking Serial output. The non-blocking millisDelay timerclass and a loopTimer class are also included in the SafeString library.