Forum: Mikrocontroller und Digitale Elektronik Komisches verhalten beim lesen von Array


von Nils K. (flying_nils)


Lesenswert?

Hallo,
Ich arbeite an einem kleinen Projekt, in dem ich mit einem Attiny817 
eine 25 Byte lange UART-Nachricht lese und diese anschließend mit 
Bit-Verschiebungen weiterverarbeite (es handelt sich um ein SBUS Signal 
eines RC Empfängers).
Wenn ich jedoch mein rec[] Array auslese, verändert dieses sich ganz 
komisch.
Mein Array ist so definiert:
1
volatile uint8_t rec[48]; //(habs auch schon als uint16_t probiert)
(es ist extra groß, um einen Überlauf bei verpassen des Nachricht-endes 
zu vermeiden)
Zum testen habe ich nach dem vollständigen Empfang jede Stelle des 
Arrays auf 1 gesetzt und die stelle 0 ausgegeben. Vor dem erneuten auf 1 
schreiben habe ich die stelle 0 auch ausgegeben um zu sehen, was für ein 
Wert sie hatte.
1
 
2
char strr[20];
3
sprintf(strr,"=%d \r\n", (int)rec[0]);
4
printString(strr);
5
for (int i = 0; i < 25; i++)
6
{
7
      rec[i] = 1;
8
}
9
char strrr[20];
10
sprintf(strrr,"-%d \r\n", (int)rec[0]);
11
printString(strrr);
Aus dem zweiten print kommt wie zu erwarten "1", aus dem ersten kommt 
jedoch abhängig von meinem restlichen Programm was ganz anders raus, 
obwohl ich nie in das Array schreibe. Ich habe zuerst besagte 
Weiterverarbeitung auskommentiert und aus beiden prints eine "1" 
bekommen. Wenn ich nun aber eine beliebige Zeile einkommentiere, selbst 
wenn diese überhaupt nichts mit der stelle 0 zu tun hat, wird diese 
trotzdem verändert.
Mit
1
channels[15] = (uint16_t) ((rec[21]>>5|rec[22]>>3) & 0x07FF);
kommt aus dem ersten print eine "0" raus.
Mit
1
channels[15] = (uint16_t) ((rec[21]>>5|rec[22]) & 0x07FF);
oder
1
channels[15] = (uint16_t) ((rec[21]|rec[22]>>3) & 0x07FF);
kommt aus dem ersten print eine "1" raus, obwohl ich an der 0. stelle 
gar nichts verändere.
Teilweise ist auch, mit klammern um den Verschiebungen, eine "8" oder 
"9" gekommen. Ich habe es auch schon mit mehr als nur dem einen 
(uint16_t) cast probiert, da es ja scheinbar etwas damit zu tun haben 
muss, aber funktioniert hat es danach auch nicht. Hat hier vielleicht 
jemand eine Idee, warum sich das Array so komisch verhält, bzw. warum 
ich eine stelle am fast anderen ende des Arrays beeinflusse?
Danke und Gruß,
Nils

von Wolfgang (Gast)


Lesenswert?

Nils K. schrieb:
> (es ist extra groß, um einen Überlauf bei verpassen des Nachricht-endes
> zu vermeiden)
Das kann doch wohl kein Argument für die Array-Größe sein. Was passiert, 
wenn du das Ende zwei mal verpasst?
Reduzierte Fehler-/Absturzwahrscheinlichkeit?

> Hat hier vielleicht jemand eine Idee, warum sich das Array so komisch
> verhält, bzw. warum ich eine stelle am fast anderen ende des Arrays
> beeinflusse?

Was liegt denn vor dem Array im Speicher?

Guck dem Array und deinen Variable, notfalls auch den Registern im 
Simulator oder besser im Debugger auf die Finger.

von Dirk B. (dirkb2)


Lesenswert?

Wie und wo ist channels definiert?

Was in channels[15] landen soll, steht in rec[0].
Denn das 0 oder 1 ist das Ergebnis der Berechnung rechts vom =

Also Speicher- oder Indexüberlauf.

: Bearbeitet durch User
von Adam P. (adamap)


Lesenswert?

Nils K. schrieb:
> char strr[20];
> sprintf(strr,"=%d \r\n", (int)rec[0]);
> printString(strr);
> for (int i = 0; i < 25; i++)
> {
>       rec[i] = 1;
> }
> char strrr[20];
> sprintf(strrr,"-%d \r\n", (int)rec[0]);
> printString(strrr);
>
> Aus dem zweiten print kommt wie zu erwarten "1", aus dem ersten kommt
> jedoch abhängig von meinem restlichen Programm was ganz anders raus,
> obwohl ich nie in das Array schreibe.

Nunja, wenn du die strr[20] erzeugst (1 Zeile), dann ist der Inhalt 
undefiniert - deshalb kommt bei der ersten Ausgabe einfach irgendwas, 
das was grad im RAM an der Stelle liegt.

von my2ct (Gast)


Lesenswert?

Adam P. schrieb:
> Nunja, wenn du die strr[20] erzeugst (1 Zeile), dann ist der Inhalt
> undefiniert - deshalb kommt bei der ersten Ausgabe einfach irgendwas,
> das was grad im RAM an der Stelle liegt.

Sicher?

"All array elements that are not initialized explicitly are 
zero-initialized."
https://en.cppreference.com/w/c/language/array_initialization
https://www.cs.uic.edu/~jbell/CourseNotes/C_Programming/Arrays.html

von Christian K. (the_kirsch)


Lesenswert?

Globale und Lokale Statische Variablen werden mit 0 vorgelegt.

Lokale Variablen aber nicht, die landen auf dem Stack, und haben den 
Inhalt, der vorher da im Speicher war.

von Wolfgang (Gast)


Lesenswert?

Christian K. schrieb:
> Lokale Variablen aber nicht, ...

Und woran erkennst du, dass die lokal ist?
Aus dem Fehlerverhalten oder sagt dir das deine Glaskugel bei Ansicht 
des Code-Fragments? ;-)

von Dirk B. (dirkb2)


Lesenswert?

Wenn bei einer Arrayinitialisierung nur für einen Teil des Arrays Werte 
angegeben werden, wird der Rest mit 0 gefüllt.

static und global Variablen werden, wenn nichts anderes angegeben wird, 
mit 0 initialisiert.

von Nils K. (flying_nils)


Lesenswert?

Das str[20] ist nur für meine print Ausgabe und deswegen einfach groß um 
den Überlauf bei 32bit zahlen zu vermeiden (aus anderem Projekt 
kopiert). In sprintf habe ich ein "-" und ein "=" voresetzt, um die 
beiden nicht zu verwechseln, heißt bei dem oberen print block erhalte 
ich "=(zahl)" und bei dem unteren "-(zahl)".

Das Array "channels" war als "volatile uint16_t channels[15];" 
definiert, was heißt, dass es die stelle 15 gar nicht gab. Wie immer ist 
es solch eine Kleinigkeit, die das ganze kaputt macht. Es ist jetzt als 
"channels[16]" definiert und funktioniert.
Danke für die Antworten und Tipps, soweit hatte ich gar nicht gedacht.

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.