Hallo,
unten stehender Code soll meine Eigabe über BT einfach parsen und mir
die entsprechende Datei im SPIFFS auf mein Terminal (Handy) holen.
Klappt auch aber ich bin wohl mit String etwas durcheinander gekommen.
Da die String Klasse (und auch Stream) sehr komfortabel sind nutze ich
sie auch und versuche nur "by reference" zu arbeiten. Probleme mit
Speicherfragmentierung hatte ich noch nie.
Hier schaue ich, ob nur "show" gesendet wurde oder "show filename" kam.
Der Fehler wird sichtbar in der Ausgabe. Der dateiname dname ist am Ende
mit ^@ versehen, also vermutlich nicht Null Terminiert. Ich suche das
Leerzeichen und zerschneide damit den String. Den zweiten Tag übergebe
ich der SPIFFS Funktion, die die Datei ausliest. Mit String Filename
klappt es wo der aktuelle Dateiname global steht, mit dem zerteilten
String nicht.
Im BT Terminal Programm sende ich Befehle NULL Terminiert ab, das kann
man ankreuzen ob /r/n oder NULL oder was anderes.
debugln(dname) zeigt "230323.txt^@ an. Erzeugt substring keinen Null
terminierten Strring?
Sebastian W. schrieb:> Hab deinen Code nicht nachvollzogen, aber: ^@ könnte die Darstellung> eines \0-Zeichens durch dein Terminal sein.
Dann wäre das ja bei den anderen Strings auch so. ist es aber nicht. Ich
versuche es als letzte Möglichkeit alles in ansi c umzu schreiben mit
string funktionen aber das ist eben mühsamer.
War eh noch ein Fehler drin, das Root zeichen fehlte
String dname = "/" + mystring.substring(pos+1); // Hole Dateiname
Ist auch nur Gebastel auf Gut Glück....
Thorsten M. schrieb:> Dann wäre das ja bei den anderen Strings auch so. ist es aber nicht.
Das meine ich nicht. Wenn ^@ das \0-Zeichen am Stringende sein sollte,
dann dürfte es gar nicht auf dem Terminal erscheinen. Das könnte nur
passieren wenn das Längenfeld in der String-Klasse nicht mit dem Inhalt
des Zeichenkettenpuffers des Strings übereinstimmt. Und das deutet auf
Speicherkorruption hin. Womöglich existiert der String an der Stelle, wo
er ausgegeben wird, schon gar nicht mehr?
LG, Sebastian
Sebastian W. schrieb:> Womöglich existiert der String an der Stelle, wo> er ausgegeben wird, schon gar nicht mehr?
Wie meinst Du das? Soll ich ihn mal global volatile definieren? Nur zur
Info. Hänge ich ein '\0' mit dran habe ich zweimal ^@^@ da stehen. Also
hast Du wohl recht.
String dname;
void HandleBT(String mystring) {
nach außern verlegen klappt aber auch nicht.
Grübel... grübel...
Irgend W. schrieb:> Ich glaube du vermischst hier "Null-Terminierte Char-Arrays" und die> String-Klasse munter miteinander. Und dann gibt es auch noch einen> Unterschied zwischen "string" und "String". Bei den Klassen heißt eine> Null nicht automatisch Stringende.
Das hilft mir bei meinem Problem jetzt aber auch nicht weiter. Woher
diese extra zeichen kommen? Ich benutze String seit jeher und nie gab es
Probleme damit. Leider habe ich keinen echten Debugger wie beim stm32,
so dass ich nicht eben ins Ram schauen kann wie es da aussieht.
Die Stringlaenge wird wohl irgendwo im private Teil des Objektes
stehen,.
Ist übrigens egal ob by reference oder by value, gleiches Ergebnis.
Ich gebe für heute auf. Da stimmt was nicht.
show unsinn müsste eine fehlermeldung erzeugen, dass die Datei nicht
exisiert. Tut es aber nicht, rennt er so drüber. Und der Rest hat
vermutlich mit dem Terminal zu tun. String können genausogut \r\n
terminiert sein. Oder eben gar nicht, wenn die Länge irgendwo steht.
1
/* Zeige das heutige File */
2
voidshowTodayFile(String*dateiname){
3
4
Stringlokal=*dateiname;
5
6
/* Datei öffnen */
7
debugln("Oeffne Datei "+lokal);
8
Filefile=SPIFFS.open(lokal);
9
if(!file){
10
debugln("showTodayFile: Failed to open "+lokal+" for reading");
Thorsten M. schrieb:> if (mystring.indexOf("show") != -1) {> int pos = mystring.indexOf(' ');
Das solltest du nochmal überdenken.
Überleg was bei Eingaben
" show filename"
"show filename"
"filename show"
"show filename "
usw. passiert.
Εrnst B. schrieb:> Das solltest du nochmal überdenken.
Ich denke heute nicht mehr und ich habe die Tasten auf Makros liegen,
Fehler abfangen wird nicht gemacht.
Mit mystring.startWith sucht man am Anfang ....
Thorsten M. schrieb:> Ich denke heute nicht mehr
Dann mach wenigstens ganz ohne Nachdenken ein
> if (mystring.indexOf("show") == 0) {
draus.
Edit: Oder startsWith, wie du sagst. Hast ja doch nachgedacht :)
Dann muss "show" immer am Anfang des Befehls stehen, was ja mit deinen
Makros kein Problem ist.
Und hier:
> File file = SPIFFS.open(lokal);
solltest du angeben, dass du die Datei zum Lesen öffnen willst. Sonst
wird einfach eine Datei mit falschem Namen angelegt, und dein
> if (!file) {
Check läuft ins Leere.
Εrnst B. schrieb:> solltest du angeben, dass du die Datei zum Lesen öffnen willst. Sonst> wird einfach eine Datei mit falschem Namen angelegt, und dein
Nicht ganz. Default ohne Parameter ist lesen. Und gelesen habe ich alles
was drüber gibt heute, seit 10 Uhr. Sitze hier im Schlafanzug, den
ganzen Tag nur Kaffee und Kippen. Ah, Berlin Entscheid auch gescheitert,
sehr gut. Gibt ja noch Vernünftige dort.
Ende für Heute...
Ich glaube da haben wir den Übeltäter... so sieht das aus was diese
Zeile erzeugt.
String dname = "/" + mystring.substring(pos + 1) + "txt";
Das BT Terminal stellt diese Null als ^@ dar.
substring scheint entweder fehlerhaft zu sein oder das ist ein Feature,
dass da eine Null zwischenrutscht. Abgesehen davon dass ich den Punkt
vergessen habe. Ich werde heute abend mal ne Kanne Kaffee bereitstellen
und schreibe den ganzen Ramsch auf string Funktionen um, da weiss ich
wenigstens was bei rauskommt. ChatGPT leistet da auch sehr gute Hilfe.
Constanze H. schrieb:> du scheinst hier String und cstring zu mischen.
Ich kann mit dem Informationsgehalt von Einzeilern leider nichts
anfangen. Auch wenn das in Chats so üblich ist. Ich mische gar nichts.
Da rutscht eine Null rein wo keine hin gehört. Ist so!
Das spuckt die Code analyse von ChatGPT aus:
Es sieht so aus, als ob das Problem darin besteht, dass Sie einen
Pointer auf dname an die Funktion showTodayFile übergeben, obwohl dname
eine lokale Variable in der if-Anweisung ist. Sobald die if-Anweisung
beendet ist, wird die Variable dname außerhalb ihres Gültigkeitsbereichs
fallen gelassen und ihr Speicherplatz wird möglicherweise von anderen
Daten überschrieben werden. Der Pointer, der an showTodayFile übergeben
wird, würde daher auf einen ungültigen Speicherbereich zeigen, was zu
unvorhersehbarem Verhalten führen kann.
Um dieses Problem zu beheben, könnten Sie stattdessen eine Variable vom
Typ String deklarieren und diese dann an showTodayFile übergeben,
anstatt einen Pointer auf dname zu übergeben. Hier ist eine modifizierte
Version des Codes:
Thorsten M. schrieb:> String dname = "/" + mystring.substring(pos + 1) + "txt";
Wo genau steht denn diese Zeile in dem gezeigten Code oben?
Thorsten M. schrieb:> Das spuckt die Code analyse von ChatGPT aus:>> Es sieht so aus
ChatGPT sollte besser auch ein paar Tassen Kaffee trinken, wenn sich das
auf den von dir gezeigten Code bezieht. Wenn du dem natürlich anderen
Code gegeben hast, kann das durchaus sein.
Oliver
Thorsten M. schrieb
>unten stehender Code soll meine Eigabe über BT einfach parsen
Nur so eine Frage am Rande: welche Hardware benutzt du auf beiden
Seiten?
Thorsten M. schrieb:> show unsinn müsste eine fehlermeldung erzeugen, dass die Datei nicht> exisiert. Tut es aber nicht, rennt er so drüber.
Warum sehe ich beim open kein "r"?
Thorsten M. schrieb:> void showTodayFile(String *dateiname) {
Einen String als Zeiger übergeben?
Scheint mir Unsinnig.
Ich denke es liegt eher daran, dass der String, den deine
HandleBT-Funktion übergeben bekommt, am Ende ein NULL enthält. Dann ist
die NULL natürlich auch im Ergebnis des substring-Aufrufs vorhanden.
An deiner Stelle würde ich prüfen, woher die NULL am Ende kommt.
Entweder dann an der Aufruf-Stelle ändern oder am Anfang der
HandleBT-Funktion abschneiden (bzw. trimmen).
Christoph M. schrieb:> Nur so eine Frage am Rande: welche Hardware benutzt du auf beiden Seiten
Ein Smartphone und einen Esp32. Strings werden mit cr lf jetzt
terminiert beim Senden. Ich teste das heite abend mal mit String
Konstanten statt mit dem Terminal Programm
open in spiffs erwartet einen cstring aka. const char * path als
Argument, keinen String. Wie man diesen cstring erzeugt, habe ich im
post verlinkt. Der Rest ist deine Sache.
Constanze H. schrieb:> open in spiffs erwartet einen cstring aka. const char * path als> Argument, keinen String.
Das ESP32-SPIFFS unterscheidet sich von der ESP8266-Variante, bin ich
oben auch schon drüber gestolpert...
dort gibt's
Constanze H. schrieb:> open in spiffs erwartet einen cstring aka. const char * path als> Argument, keinen String. Wie man diesen cstring erzeugt, habe ich im> post
Ich schätze wirklich jede Hilfe. Aber wenn jemand ohne jeden Nachweis
falsche Behauptungen aufstellt dann winke ich auch ab. Andere schrieben
es schon, spiffs ist ein Fs Objekt und das lässt String zu. Rechter
Mausklick und schon sieht man das. Ich werde das alles trotzdem
umschreiben ohne String. Ist zwar aufwendiger mit der stdlib aber ich
weiss da genau was da passiert.
Julian L. schrieb:> Ich denke es liegt eher daran, dass der String, den deine> HandleBT-Funktion übergeben bekommt, am Ende ein NULL enthält. Dann ist> die NULL natürlich auch im Ergebnis des substring-Aufrufs vorhanden.
sehe ich auch so. Ein String kann '\0' Zeichen enthalten.
1
Strings("test");
2
s+='\0';
3
Strings2=s.substring(2);
4
Serial.println(s2.length());
liefert Länge = 3, die 0x00 ist im String s und Substring s2 enthalten.
J. S. schrieb:> sehe ich auch so. Ein String kann '\0' Zeichen enthalten.
Yupp... Immer gefährlich zwei Systeme zu mischen. Daher zurück zu den
Leisten strtok, strstr, strcpy usw
J. S. schrieb:> Der Fehler passiert einfach schon vorher im nicht gezeigten Code.
String dname = "/" + mystring.substring(pos + 1) + ".txt";
Hier passiert er! Ich bin es gewohnt, dass der + Overload Operator
Strings nahtlos zusammen schreibt als Ascii Zeichen. Und das ist eben
nicht der Fall hier.
Die Stringklasse funktioniert und es wird 'nahtlos' aneinandergehängt.
Im Aufruf von HandleBT(String) hat String schon eine Null dran pappen.
Gib am Anfang von HandleBT() mal mystring.length() aus und zähle die
Zeichen.
Läuft!
Da die Befehle eh auf Makro Tasten liegen und feste Größen bestehen ist
die Null jetzt weg. Die kommt von irgendwoher rein, vermutlich vom BT
Terminal. Und Kollegen sagten mir auch dass String keinen Terminator
hat, die Länge wird ständig angepasst von den Methoden, je nachdem wie
der verwurstelt wird.
Thorsten M. schrieb:> Und Kollegen sagten mir auch dass String keinen Terminator hat, die> Länge wird ständig angepasst von den Methoden, je nachdem wie der> verwurstelt wird.
Da hilft es, den Quellcode von WString.h und auch WString.cpp mal
ernsthaft zu studieren ...
LG, Sebastian