for loop funtioniert nicht

#3841047
Lesenswert?

Hallo,
woran kann es liegen dass:
1
for (uint8_t i=0; i<16; i++)
2
{
3
   if(SetupWK->rec.Eep_BESC_Layout[i+1]==0x23)
4
   {
5
       ESCLayoutName[i] = 0;
6
       break;
7
   }
8
   else  
9
   {
10
        ESCLayoutName[i] = SetupWK->rec.Eep_BESC_Layout[i+1];
11
   }
12
}
nicht funktioniert (läuft über 16 hinaus immer weiter)?

Setze ich
1
for (uint8_t i=0; i<15; i++)
 funktioniert es, ebenfalls wenn ich i volatile deklariere.
Ebenfalls funktioniert folgendes:
1
for (uint8_t i=1; i<16; i++)
2
{
3
   if(SetupWK->rec.Eep_BESC_Layout[i]==0x23)
4
   {
5
        ESCLayoutName[i-1] = 0;
6
        break;
7
   }
8
   else  
9
   {
10
        ESCLayoutName[i-1] = SetupWK->rec.Eep_BESC_Layout[i];
11
   }
12
}
Mach ich da einen Fehler oder oder die Optimierung?
Ich benutze Atmel Studio 6.2.
#3841058
Lesenswert?

Müsste eigentlich funktionieren. Ändert sich das Verhalten, wenn du die 
Optimierung veränderst oder ausschaltest?

Achim X. schrieb:
> nicht funktioniert (läuft über 16 hinaus immer weiter)?
Wie stellst du das fest und welchen Compiler (und Version) benutzt du?

Ändert sich das Verhalten, wenn du den Schleifenkopf testweise 
abänderst? z.B.:
1
for(uint8_t i = 0; i != 16; i++) { ... }
2
for(uint8_t i = 0; i <=15; i++) { ... }
Gast #3841066
Lesenswert?

Achim X. schrieb:
> Hallo,
> woran kann es liegen dass:
>
1
for (uint8_t i=0; i<16; i++)
2
> {
3
>    if(SetupWK->rec.Eep_BESC_Layout[i+1]==0x23)
4
>    {
5
>        ESCLayoutName[i] = 0;
6
>        break;
7
>    }
8
>    else
9
>    {
10
>         ESCLayoutName[i] = SetupWK->rec.Eep_BESC_Layout[i+1];
11
>    }
12
> }
> nicht funktioniert (läuft über 16 hinaus immer weiter)?

Möglicherweise wird 'i' (auf dem Stack liegend) überschrieben?

> mit
1
for (uint8_t i=0; i<15; i++)
> funktioniert es, ebenfalls

Wenn's bis 15 geht und bei 16 nicht mehr geht...


> wenn ich i volatile deklariere.
Dann liegt die Variable möglicherweise woanders und wird nicht 
überschrieben.

Ist denn

rec.Eep_BESC_Layout[..]

mit [16] oder [17] oder größer angelegt?
#3841072
Lesenswert?

Hier das listing:
1
for (uint8_t i=0; i<16; i++)
2
{
3
   if(SetupWK->rec.Eep_BESC_Layout[i+1]==0x23)
4
   {
5
       ESCLayoutName[i] = 0;
6
       break;
7
   }
8
   else  
9
   {
10
        ESCLayoutName[i] = SetupWK->rec.Eep_BESC_Layout[i+1];
11
   }
12
}

0000135c <CopyESCLayoutName>:
    135c:  80 91 02 01   lds  r24, 0x0102
    1360:  90 91 03 01   lds  r25, 0x0103
    1364:  20 e0         ldi  r18, 0x00  ; 0
    1366:  e2 2f         mov  r30, r18
    1368:  f0 e0         ldi  r31, 0x00  ; 0
    136a:  dc 01         movw  r26, r24
    136c:  ae 0f         add  r26, r30
    136e:  bf 1f         adc  r27, r31
    1370:  af 5b         subi  r26, 0xBF  ; 191
    1372:  bf 4f         sbci  r27, 0xFF  ; 255
    1374:  3c 91         ld  r19, X
    1376:  e0 5b         subi  r30, 0xB0  ; 176
    1378:  fc 4f         sbci  r31, 0xFC  ; 252
    137a:  33 32         cpi  r19, 0x23  ; 35
    137c:  11 f4         brne  .+4        ; 0x1382 
<CopyESCLayoutName+0x26>
    137e:  10 82         st  Z, r1
    1380:  08 95         ret
    1382:  30 83         st  Z, r19
    1384:  2f 5f         subi  r18, 0xFF  ; 255
    1386:  ef cf         rjmp  .-34       ; 0x1366 
<CopyESCLayoutName+0xa>

Und dann hier:
1
for (uint8_t i=1; i<16; i++)
2
{
3
   if(SetupWK->rec.Eep_BESC_Layout[i]==0x23)
4
   {
5
        ESCLayoutName[i-1] = 0;
6
        break;
7
   }
8
   else  
9
   {
10
        ESCLayoutName[i-1] = SetupWK->rec.Eep_BESC_Layout[i];
11
   }
12
}

0000135c <CopyESCLayoutName>:
    135c:  20 91 02 01   lds  r18, 0x0102
    1360:  30 91 03 01   lds  r19, 0x0103
    1364:  e0 e5         ldi  r30, 0x50  ; 80
    1366:  f3 e0         ldi  r31, 0x03  ; 3
    1368:  81 e0         ldi  r24, 0x01  ; 1
    136a:  90 e0         ldi  r25, 0x00  ; 0
    136c:  d9 01         movw  r26, r18
    136e:  a8 0f         add  r26, r24
    1370:  b9 1f         adc  r27, r25
    1372:  a0 5c         subi  r26, 0xC0  ; 192
    1374:  bf 4f         sbci  r27, 0xFF  ; 255
    1376:  4c 91         ld  r20, X
    1378:  43 32         cpi  r20, 0x23  ; 35
    137a:  29 f4         brne  .+10       ; 0x1386 
<CopyESCLayoutName+0x2a>
    137c:  fc 01         movw  r30, r24
    137e:  e1 5b         subi  r30, 0xB1  ; 177
    1380:  fc 4f         sbci  r31, 0xFC  ; 252
    1382:  10 82         st  Z, r1
    1384:  08 95         ret
    1386:  41 93         st  Z+, r20
    1388:  01 96         adiw  r24, 0x01  ; 1
    138a:  80 31         cpi  r24, 0x10  ; 16
    138c:  91 05         cpc  r25, r1
    138e:  71 f7         brne  .-36       ; 0x136c 
<CopyESCLayoutName+0x10>
    1390:  08 95         ret
#3841093
Lesenswert?

Danke für den Hinweis. Ich hab gerade erst bemerkt, dass ich eigentlich 
tatsächlich nur 14 Bytes brauche.
Allerdings: SetupWK->rec.Eep_BESC_Layout liegt aber innerhalb einer 
größeren gepackten Struktur, da sollte ein Byte Überlappung nichts 
machen.
Es würde auch nicht erklären warum volatile funktioniert.
#3841106
Lesenswert?

Achim X. schrieb:
> Allerdings: SetupWK->rec.Eep_BESC_Layout liegt aber innerhalb einer
> größeren gepackten Struktur, da sollte ein Byte Überlappung nichts
> machen.

FALSCH!

Johannes , Du hast tatsächlich richtig gelegen!!!
Ich habe mal
1
char Eep_BESC_Layout[16];
auf
1
char Eep_BESC_Layout[17];
innerhalb des Records gesetzt.
Und schon funktioniert die Sache.
Die Grenze des Arrays scheint dem Compiler irgendwie "bewusst" zu sein.

Warum dann volatile funktioniert, ist mir zwar immer noch ein Rätsel...

Vielen, vielen Dank für alle Antworten!
Moderator Persönliche Seite #3844912
Lesenswert?

Meines Erachtens fehlt unter der for-Schleife eine Terminierung, 
nämlich:

  ESCLayoutName[i] = 0;

Grund: Tritt innerhalb der ersten 16 Zeichen kein 0x23 auf, wird der 
String nicht terminiert.

Achim X. schrieb:
> Ich habe mal
>
1
char Eep_BESC_Layout[16];
> auf
>
1
char Eep_BESC_Layout[17];
> innerhalb des Records gesetzt.
> Und schon funktioniert die Sache.

Damit hast Du Dir Deine Terminierung am Ende künstlich geschaffen. Wenn 
das aber keine globale bzw. static Variable ist, dann ist das ein 
Glücksspiel und kommt darauf an, was vorher auf dem Stack so rumlag.

Richtig ist:
1
  char Eep_BESC_Layout[17];   // 16 Zeichen + 1 Byte fuer Terminierung
und
1
  ESCLayoutName[i] = 0;       // Unter(!) der for-Schleife

Als letztes kannst Du dann das
1
  ESCLayoutName[i] = 0;       // über dem Break

über dem break-Statement (in der for-Schleife) rauslöschen. Das ist 
nämlich nun doppelt gemoppelt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren