Forum: Compiler & IDEs for loop funtioniert nicht


von Achim X. (hallali)


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.

von Klaus W. (mfgkw)


Lesenswert?

Sieht m.E. eigentlich richtig aus.

Ist das wirklich der Quelltext exakt, oder nur so ähnlich?

von Achim X. (hallali)


Lesenswert?

Ist exakt der Quelltext.

von B. S. (bestucki)


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++) { ... }

von Sepp (Gast)


Lesenswert?

Achim X. schrieb:
> funktioniert es, ebenfalls wenn ich i volatile deklariere.

ISR?

von NurEinGast (Gast)


Lesenswert?

Vielleicht ein Speicherproblem ?
Wie ist denn ESCLayoutName[] definiert ?

von Mehmet K. (mkmk)


Lesenswert?

Schuss ins Blaue:
Bei 15 Durchlaeufen keine Probleme.
Bei 16 Durchlaeufen Probleme.
Kann es sein, dass Array-Size von Eep_BESC_Layout[] oder ESCLayoutName[] 
zu klein bemessen ist und daruch das Stack durcheinander gewürfelt wird?

von Achim X. (hallali)


Lesenswert?

char ESCLayoutName[16];

ISR sind nicht im Spiel.

von B. S. (bestucki)


Lesenswert?

Nachtrag:
Ansonsten mal das Assembler-Listing anschauen.

von NurEinGast (Gast)


Lesenswert?

char ESCLayoutName[16];

==> ESCLayoutName[0] bis ESCLayoutName[15] sind erlaubt.
ESCLayoutName[16] ruiniert den Speicher.

von Norbert (Gast)


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?

von Norbert (Gast)


Lesenswert?

...erstaunlich wieviele Antworten es in einer Minute gibt...

von NurEinGast (Gast)


Lesenswert?

Sorry - zu schnell auf "Absenden gedrückt".
Wollte noch dazuscheinen

   passt ja eigentlich ....

von Achim X. (hallali)


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

von Johannes M. (johannesm)


Lesenswert?

Achim X. schrieb:
> for (uint8_t i=0; i<16; i++)
> {
>    if(SetupWK->rec.Eep_BESC_Layout[i+1]==0x23)

Achim X. schrieb:
> char ESCLayoutName[16];

Das passt nicht.
Wenn i bis 15 zählt und in der ArrayID +1 addiert wird, bist du 
außerhalb deines Arrays.

von Achim X. (hallali)


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.

von Achim X. (hallali)


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!

von Frank M. (ukw) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
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.