Permalänk
Medlem

Sträng object, Arduino

Håller på med ett hyffsat komplext Arduino-projekt(i mitt tycke).
Skickar en massa data via seriellt gränssnitt till Arduinon från en dator, t.ex
"A122B325.34E245F23.45"
Denna data mottager jag utan problem och lagrar nu i ett object av typen String.

Anledningen är att det finns många färdiga funktioner för stränghanteringen om jag vill parsa datan och modifiera strängen etc..

Men man läser ju lite här och där att en char array är att föredra alla dagar då detta är bra mycket mer minneseffektivt och att om man använder strängar så kan man få slut på minne tillslut..

Min fråga är egentligen,
om man använder String och skriver över den säg 20000 gånger kommer den att behöva mer minne för varje gång eller använder den samma mängd minne vid varje "överskrivning"(Om längden på strängen är lika lång varje gång)?
Jag vet ju nu att längden på strängen kommer aldrig att vara längre än ca 50 tecken.

Eller är det mer "rätt" oavsett att använda sig utav en char array med fixerad storlek(64 byte skulle säkert räcka bra för mig) och skriva egna parsing funktioner istället?

Visa signatur

Bara gammalt skräp...

Permalänk
Medlem

Jag har inte använt mycket Arduino så kan inte utala mig exakt hur det fungerar men då det i grunden är c++ med lite hjälp bibliotek så ska det ju inte vara någon större skillnad om de inte gjort String klassen fel vilket borde har upptäckts kan man tycka. Eller om du gör något fel i din kod med new/delete etc. Det gäller dock även för om du gör det som arrayer så det borde inte påverka heller.

Permalänk
Medlem

När en variabel uppdateras och får ett nytt värde tillsätts inget mer minne utan använder samma tilldelat minne som den fick när man deklarerade den från början. Den deklarerar ju sig inte igen till fler minnesplatser varje gång den uppdateras.

Visa signatur

| Fractal Design R4 White | Intel I5 6600k@4Ghz| Asus Z170-A | MSI GTX 970 @1425Mhz | Corsair 16GB DDR4 2133mhz | Samsung 840 250GB | Corsair 650Watt nätagg |

https://soundcloud.com/symbolofficial

Permalänk
Medlem
Skrivet av vikham:

När en variabel uppdateras och får ett nytt värde tillsätts inget mer minne utan använder samma tilldelat minne som den fick när man deklarerade den från början. Den deklarerar ju sig inte igen till fler minnesplatser varje gång den uppdateras.

Det borde ju vara så och det låter ju rimligt.
Men om vi med tanken leker med följande case att jag har en kod som ser ut så här:

String myString; myString = "test"; //Denna sträng tar nu låt oss säga 10 byte i minne myString = "testmenlängre"; //Nu behöver strängen 9 byte mer i minne totalt 19 myString = "apa"; //Kortare sträng vilket innebär att den tar bara 9 byte i minne(1 kortare än första tilldelningen)

Har nu myString lagt "beslag" på 19byte i minnet för all framtid eller använder den nu bara 9 och de 10 övriga(som behövdes när den var längre) är lediga för processorn att använda till annat?

Jag är inte så intresserad av att optimera körtiden för stränghanteringen så även om en char array är snabbare att arbeta med så gör inte det så mycket då det ändå bara handlar om µs(antar jag) kontra att använda ett String-objekt.
Min oro är däremot att väldigt många skriver att användning av String kan få oanade konsekvenser som slut på minne, fragmenterad minnesanvändning vilket kan få processorn att låsa sig eller bit-fel. Detta vill jag givetvis undvika
Det som alla verkar haussa med en char-array är att man har stenkoll på minnesanvändningen.

Men antar att det bara är att testa och se vad som händer, jag ska inte göra särskilt avancerad sträng-hantering så jag har ju alla möjligheter att använda en char-array, lite mer jobb bara då det inte verkar finnas färdiga funktioner för det som jag vill göra.
Jag vet ju en som kan allt om detta dock @Yoshman

Visa signatur

Bara gammalt skräp...

Permalänk
Medlem

Ok, nu fattar jag vad du menar. Jag har själv inte använt Arduino så mycket men som jag förstår sker minnes allokeringen mycket automatiskt där, dvs den lägger till eller tar bort minne som behövs automatiskt utan att man själv behöver göra något. (Om man själv inte går in och bestämmer den). Om detta dock innebär att minne som inte längre används inte görs fri är det ju ett problem.

För att få bukt på problemet i C så skapar man sin egna "dynamic memory allocation" med funktionerna malloc(), realloc(), calloc() och free() som finns i standardbiblioteket stdio.h. Det finns nog motsvarande funktioner i Arduino språket.

Visa signatur

| Fractal Design R4 White | Intel I5 6600k@4Ghz| Asus Z170-A | MSI GTX 970 @1425Mhz | Corsair 16GB DDR4 2133mhz | Samsung 840 250GB | Corsair 650Watt nätagg |

https://soundcloud.com/symbolofficial

Permalänk
Medlem

@bardbard: Libraries mappen var borttagen på deras github och längre än så orkade jag inte kolla.

Kan inte exakt hur tex std::string är implementerad när det gäller hur mycket minne den allokerar i konstruktorn. Dock brukar de vara sådana att om du försöker skriva längre än vad som får plats så dubblerar den minnet som är allokerat så att den inte ska behöva allokera nytt varje gång du skriver till den.

Det enda du kanske kan behöva tänka på är att de brukar aldrig minska mängden allokerat minne automatiskt. Dvs om du skriver en 100 bytes sträng till den och sen en 10 bytes sträng så kommer den fortfarande att ha allokerat minne för de 100 bytes som behövdes tidigare. Men om du som i ditt exempel bara ska ha samma längd och bara skriva över värdet många gånger så ska inte minnesanvändningen öka.

Permalänk
Datavetare

Här är ett tips man inte ser så ofta: globala variabler är det bästa vän!

Normalt vill sky sådan design som pesten, men det är lägen där man inte är begränsad till någon enstaka kB RAM och ett totalt flash-utrymme på < 64 kB.

Frågan var

Citat:

om man använder String och skriver över den säg 20000 gånger kommer den att behöva mer minne för varje gång eller använder den samma mängd minne vid varje "överskrivning"(Om längden på strängen är lika lång varje gång)?
Jag vet ju nu att längden på strängen kommer aldrig att vara längre än ca 50 tecken.

Rent logiskt är svaret: nej, instanser av "String" i Arduino frigör alltid sitt minne. I den version som är aktuellt för tillfälle allokeras på byten när så mycket minne som behövs.

Rent praktiskt: är en väldigt överhängande risk att ditt program kommer krascha när det kört tillräckligt länge om storleken på strängen är någorlunda stor och dess längd varierar en hel del.

Orsaken är att systemet du kör på har en extremt simpel heap-implementationen (datastrukturen som hanterar fritt minne) + när det bara finns någon enstaka kB RAM totalt sett är det rätt omöjligt att göra speciellt smarta saker i en heap-allokator.

Rekommenderade sättet att jobba med mikrokontrollers är att allokera allt RAM som behövs, endast exklusive det som kommer användas för automatiska variabler (de som ligger "på stacken" vid anrop). Det garanterar att programmet aldrig kan misslyckas p.g.a. brist på RAM (är även så man måste designa programvara som används i styrsystem för flygplan, tåg och liknande, just för att programmet inte ska kunna sluta fungera för att heap:en fragmenterats).

Har noterat att det finns flera implementationer av WString.h/WString.cpp (som burkar vara namnet på String klassen i Arduino). Vissa ser till att alltid allokera exakt på byte:en när vilket är en dålig idé p.g.a att man då får fragmentering även om man har alla strängobjekt globalt.

Den implementation som jag har på disken (som är den som kommer med Arduino för ESP8266, ESP32 och AVR) frigör bara minne om strängobjektets destruktor körs (d.v..s om sträng-objektet inte längre kan nås). Annars ökas bara kapaciteten vid behov, minnet återanvänds om man stoppar in en mindre sträng.

Så vad du då gör: i setup(), stoppa in dummy-strängar som är av längsta storlek du någonsin behöver. Det ser till att allt minne allokeras vid start, endera lyckas det och ditt program kommer fungera eller så kraschar det direkt.

"Crash Early
A dead program normally does a lot less damage than a crippled one."
The Pragmatic programmer

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer