Forum: Mikrocontroller und Digitale Elektronik UART, String, Array, einzelne Zeichen extrahieren


von Björn N. (bniethammer)


Lesenswert?

Hallo liebes Forum!

Ich hab ein kleines Problem beim Zerstückeln eines Strings den ich über 
die UART empfangen hab. Der String steht in dem Array buf drinn. An ganz 
bestimmten Stellen dieses Arrays stehen Informationen die ich brauche. 
Die stehen auch immer genau da, weil es so vom Protokoll vorgegeben ist. 
Zum Beispiel will ich die beiden Zeichen buf[10] und buf[11] 
hintereinander in einen String Pointer schreiben. Den Pointer brauche 
ich damit ich damit dann eine Suchanfrage in einer SQL Datenbank starten 
kann.

Kleiner Codeauszug:
1
char buf[255];
2
char *status;
3
char temp[10];
4
5
/* lese aus UART in buf ein, mache malloc für status */
6
7
temp[0] = buf[10];
8
temp[1] = buf[11];
9
temp[2] = '\0';
10
status = (char *)temp;
An dieser Stelle bricht das Programm dann mit einem segmentation fault 
ab.

Hat einer eine Idee was ich falsch mache oder wie es eleganter 
funktioniert?

Hab selbst schon mit sprintf() und mit strncat() es versucht. Aber bei 
beidem ein seg. fault.

Gruß Björn Niethammer

von Peter (Gast)


Lesenswert?

Sicher das der "segmentation fault" bei diesem Code Schnipsel auftritt, 
denn so verkehrt sieht das ganze nicht aus. Es sind alles einfache 
Zuweisungen da kann so etwas nicht passieren.

Was soll der Kommentar sagen "mache malloc für status " ich sehe im dem 
Code kein malloc.


Eventuell mal etwas mehr Code schicken.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Also hab das mal kompiliert (und probiert)... geht ohne Probleme(seg 
fault..)
1
int main() {
2
  char buf[255];
3
  char *status;
4
  char temp[10];
5
  buf[10] = 'c';
6
  buf[11]= 'd';
7
8
  temp[0] = buf[10];
9
  temp[1] = buf[11];
10
  temp[2] = '\0';
11
  status = (char *)temp;
12
  return 0;
13
}

von Björn N. (bniethammer)


Angehängte Dateien:

Lesenswert?

Hallo Peter!

Danke für deine Antwort. Ich fand meine Code eigentlich auch nicht so 
schlecht. Aber anscheind ist da ja doch noch ein gravierender Fehler 
drinn. Bin mir eigentlich super sicher das bei den Codezeilen der Fehler 
auftaucht. Denn wenn ich es weglasse funktioniert mein Programm.

Hab mal einen etwas ausführlicheren Code angehängt. Mit UART 
Initialisierung und einlesen und allem drum und dran. Die Sachen für den 
Datenbank Zugriff hab ich gelöscht denn das funktioniert auch soweit 
alles.

Zum Verständnis: Es wird etwas über UART empfangen und dann anhand des 
Zeichen an der Stelle 9 im Buffer ausgewählt was zu tun ist. Nachdem das 
vollzogen ist und der Fall das dort das Zeichen '6' drinn steht soll 
weiter geschaut werden was für Zeichen an den anderen Positionen stehen. 
Damit muss dann später eine SQL Anweisung zusammengebastelt werden a la: 
"UPDATE TABLE WHERE STATUS_ID = <Wert von status>;" Deswegen der ganze 
Aufwand.

Gruß Björn

von Peter (Gast)


Lesenswert?

Ich habe jetzt nicht alles angeschaut, aber der Fehler liegt wol hier:

temp[0] = (char)buf[10];
temp[1] = (char)buf[11];
temp[2] = '\0';
status = temp;

temp[0] = (char)buf[16];
temp[1] = (char)buf[17],
temp[2] = '\0';
zentr_nr = temp;

temp[0] = (char)buf[20];
temp[1] = (char)buf[21];
temp[2] = (char)buf[22];
temp[3] = (char)buf[23];
temp[4] = '\0';
linien_nr = temp;

temp[0] = (char)buf[24];
temp[1] = (char)buf[25];
temp[2] = '\0';
melder_nr = temp;


die Variablen status, zentr_nr, linien_nr, melder_nr sind alles Zeiger 
und habe selber keinen Inhalt - sie Zeigen nur auf das Array temp. Damit 
Zeigen alle auf die selben daten.
Der SegmentFault wird wohl kommen weil die Variablen nicht den Inhalt 
haben den du willst.

von peter (Gast)


Lesenswert?

habe jetzt nur flüchtig hingeschaut und weiss auch nicht um welchen 
Compiler es geht, aber meiner Meinung nach fehlt bei den 
Zeigerzuweisungen der Adressoperator.

Bsp.
status = &temp[0];

von Björn N. (bniethammer)


Lesenswert?

Danke Peter. Ich hatte dann auch gedacht dass es mit einem 
Adressoperator geht. Aber dann bleibt es trotzdem der gleiche Inhalt auf 
den die Zeiger zeigen. Hab mich deswegen von den Zeigern getrennt und 
dafür auch Arrays deklariert und nun funktioniert es.

Als Compiler wird übrigens ein GCC Derivat der als ARM Cross Compiler 
installiert ist genutzt.

Vielen Dank für deine Mühe.

Gruß Björn

von Matthias L. (Gast)


Lesenswert?

Du hast stehen:
1
status = (char *)temp;

Das müsste aus dem Wert in Temp (ich weiß nicht genau, als was er das 
interpretiert, als u8 oder u16) eine Adresse machen.
Also steht vorher der u16-Wert zB 40000 drin, steht nachher im Pointer 
status auch der Wert 40000.
Das ist als Adresse natürlich unsinn.

Es sollte wohl so:
1
status = &temp;

Oder vielleicht so sein:
1
status = (uint8_t*)  (uint16_t)buf[10]   |  ( (uint16_t)buf[11] << 8);

von Stefan E. (sternst)


Lesenswert?

@ Peter:
@ Matthias Lipinsky:

temp ist ein char-Array, damit ist
temp
(char*)temp
&temp
&temp[0]
hier alles äquivalent.

> Oder vielleicht so sein:
>
1
> status = (uint8_t*)  (uint16_t)buf[10]   |  ( (uint16_t)buf[11] << 8);
2
>

Und das ist doch gänzlich unsinnig. Nicht nur, dass da eine Klammerung 
fehlt, du glaubst doch nicht wirklich, dass beim OP ein Pointer per UART 
übertragen wird, der dann beim Empfänger irgendwo in den Speicher zeigt, 
oder?

von Matthias L. (Gast)


Lesenswert?

>dass beim OP ein Pointer per UART
>übertragen wird, der dann beim Empfänger irgendwo in den Speicher zeigt,
>oder?

Nein. Stimmt. Wenn dann wird ein Arrayindex übertragen.
Ich ziehe den Post zurück

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.