Forum: Compiler & IDEs Unerklärbares Verhalten


von Andreas (Gast)


Lesenswert?

Hi,

Ich habe schon eine Weile hier im Forum mitgelesen, aber jetzt weiß ich 
absolut nicht weiter!
Ich programmiere für den AT90can128 der ein Display ansteuert (die 
LCD-Funktionen) mit AVR Studio und nutze die aktuellste WinAVR Version 
um aus dem C Code entsprechenden Maschinencode zu bauen. Übertragen wird 
das ganze per PonyProg.
Hier der Code.

LCD_Cls(CO_BG_COLOR);
LCD_Print("Kalibrierung. Ok bestätigt.", STARTX, ENDY, 1, 1, 1, 
CO_PLOT_COLOR, CO_BG_COLOR);
LCD_Print("Anzahl Kalibrierungen:", STARTX, ENDY+10, 1, 1, 1, 
CO_PLOT_COLOR, CO_BG_COLOR);

uint8_t count = enter_value(STARTX,ENDY+20);

if(count == 0) return;

/*char t2[6];
const char * text2 = utoa(count, t2, 10);*/

float calib_values[count];
unsigned int i = 0;
for(;i < count; i++) {
  calibrate(i, calib_values);
}

So würde das ganze nicht laufen. Die for-Schleife terminiert nicht und 
ruft immer wieder calibrate auf. Selbst wenn ich als Durchlaufzahl 1 
angebe, so übergibt er an calibrate zum Teil den Wert 4!

Jetzt kommt aber das Kuriose! Entferne ich die Kommentare dort, sodass 
mein Wert in ein char-Array umgewandelt wird und obwohl ich diesen 
String gar nicht benutze (!!!!!) funktioniert es dann plötzlich. Hat 
jemand dafür eine Erklärung bzw. eine Lösung?

Danke

von Benedikt K. (benedikt)


Lesenswert?

Klingt nach Stackoverflow, irgendein Pointer der iregndwas überschreibt 
oder sowas in der Art.

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
was macht was macht der aufruf enter_value(..) im detail?

klingt für mich, als wenn der optimizer eine annahme trifft, die durch 
das utoa nicht mehr zutrifft.

bye kosmo

von Andreas (Gast)


Lesenswert?

static uint16_t enter_value(uint8_t x, uint8_t y) {
  uint16_t val = 0;
  char t[10];
  while((PIND & (1 << PIND1)) ) {
    const char * text = utoa(val, t, 10);

    LCD_Print(text, x,y, 1, 1, 1, CO_PLOT_COLOR, CO_BG_COLOR);

    uint16_t val2 = val;
    if(!(PIND & (1 << PIND4)) ) {
      ++val2;
    }
    else if(!(PIND & (1 << PIND7)) ) {
      --val2;
    }

    if( ((uint8_t)log10(val2)) < ((uint8_t)log10(val))) {
      LCD_Print("                        ", x,y, 1, 1, 1, CO_PLOT_COLOR, 
CO_BG_COLOR);
    }

    val = val2;

    if(!(PIND & (1 << PIND6)) ) {
      delay_ms(120);
    }
  }

  delay_ms(150);

  return val;
}

Das macht der Aufruf. Aber ums kurz zu erklären.
Er nimmt Eingaben von drei verschiedenen Tastern entgegen, die am Port D 
hängen.
D4 inkrementiert einen Wert und D7 dekrementiert einen Wert, falls sie 
gedrückt werden.
Die aktualisierten Werte werden dann auch ausgegeben.
D6 dient dazu um Verzögerungen einzubauen, sodass man auch 
Einzelschritte ausführen kann und beim inkrementieren nicht mit einem 
kurzen Druck gleich um 15 den Wert erhöht, weil der Controller so 
schnell ist.
Zusätzlich werden die Taster etwas entprellt.

Sobald ein vierter Taster gedrückt wird, wird die Schleife verlassen - 
dann steht der Wert fest und er wird zurückgegeben.
----------------
Ich kann so auch den Wert 1 eingeben, aber er gelangt trotzdem in die 
Endlosschleife.

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
soll heissen, wenn du statt
1
return val
ein
1
return 1

definierts (und den optimizer ausschaltest), kommt immer noch die 
endlosschleife?

bye kosmo

von kosmonaut pirx (Gast)


Lesenswert?

aso,
falls, ja, vermute ich ebenfalls einen fehlerhaften pointer. 
möglicherweise greift calibrate auf einen falschen index zu und somit 
irrtümlich auf das vor ihm liegende i.
bye kosmo

von Andreas (Gast)


Lesenswert?

@kosmonaut pirx

Ich habe das gerade mal so geändert, aber kurioserweise kann er nicht 
ohne Compiler Optimization kompilieren. Es ergibt immer folgenden 
Fehler:

avr-gcc.exe -mmcu=at90can128  adc.o font_f-5x8.o glcd-Display3000-211.o 
visualizer.o font_f-8x14.o main.o     -o Test.elf
e:/winavr 
20070525/bin/../lib/gcc/avr/4.1.2/../../../../avr/lib/avr5\libc.a(log.o) 
:  In function `log':(.text.fplib+0x50): relocation truncated to fit: 
R_AVR_13_PCREL against symbol `__addsf3' defined in .text section in 
e:/winavr 20070525/bin/../lib/gcc/avr/4.1.2/avr5\libgcc.a(_addsub_sf.o)

e:/winavr 
20070525/bin/../lib/gcc/avr/4.1.2/../../../../avr/lib/avr5\libc.a(modf.o 
):  In function `modf':
(.text.fplib+0x42): relocation truncated to fit: R_AVR_13_PCREL against 
symbol `__addsf3' defined in .text section in e:/winavr 
20070525/bin/../lib/gcc/avr/4.1.2/avr5\libgcc.a(_addsub_sf.o)

make: *** [Test.elf] Error 1

Also er findet da irgendeinen Fehler in einer Bibliotheksfunktion, ka, 
was ich da machen soll.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du hast vergessen, gegen die libm.a zu linken (Option -lm).

von Andreas (Gast)


Lesenswert?

Danke Jörg, für den Tipp.

Also mit deaktivierten Optimierungen funktioniert es wunderbar, auch 
ohne die Umwandlung nach String. Nur stimmen dann natürlich die delays, 
die ich benutze, nicht mehr so ganz.

Aber Schuld ist anscheinend der Compiler - nur wie fixe ich das jetzt, 
damit ich auch optimierten Code verwenden kann?

von Andreas (Gast)


Lesenswert?

Tja, nur leider hakts jetzt an anderen Stellen, sodass völlig falsche 
Ergebnisse rauskommen.

Das wurmt mich total! Ich schalte mal auf -O1

von Oliver (Gast)


Lesenswert?

>Aber Schuld ist anscheinend der Compiler - nur wie fixe ich das jetzt,
>damit ich auch optimierten Code verwenden kann?

Eigentlich kannst du mit 99,99999999999% Wahrscheinlichkeit davon 
ausgehen, daß Berechungen und for-Schleifen mit jeder Optimierungsstufe 
funktionieren. Aufpassen muß man nur mit in Interrupts genutzten 
Variablen, sowie laufzeitabhängigen Codeteilen. Das betrifft dein 
Problem aber nicht.

Der Fehler steckt irgendwo in deinem Code.

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Aber Schuld ist anscheinend der Compiler

Schau dir Benedikt's Idee ganz oben an...  ich schließe mich seiner
Meinung an.  Das klingt nach stack overflow.

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
kann ich mir bei 4k sram schwerlich vorstellen, aber unmöglich ist 
natürlich nichts.
bye kosmo

von Ronny (Gast)


Lesenswert?

> Eigentlich kannst du mit 99,99999999999% Wahrscheinlichkeit davon
> ausgehen, daß Berechungen und for-Schleifen mit jeder Optimierungsstufe
> funktionieren.

Nöö...der neue WinAvr scheint es bei höchter Optimierungsstufe an 
einigen Stellen etwas zu übertreiben.Einfach mal hier im Forum suchen...

Und wenn man z.b. in Schleifen Abbruchbedingungen hat,die durch einen 
(Timer-) Interrupt getriggert werden, kann es auch zu 
Laufzeitunterschieden kommen wenn man den Controller Rechenzeit mässig 
an seine Grenzen bringt. Dann reicht mit hoher Optimierung die 
Geschwindigkeit aus, um zur Abbruchbedingung eine Aufgabe in der 
Schleife schon erfüllt zu haben.Mit niedrigerer Optimierung dann unter 
Umständen nicht mehr.

von Uwe .. (uwegw)


Lesenswert?

Mal simuliert oder die maximale RAM-Belegung gemessen?

von Falk B. (falk)


Lesenswert?

@ Ronny (Gast)

>Nöö...der neue WinAvr scheint es bei höchter Optimierungsstufe an
>einigen Stellen etwas zu übertreiben.Einfach mal hier im Forum suchen...

>Und wenn man z.b. in Schleifen Abbruchbedingungen hat,die durch einen
>(Timer-) Interrupt getriggert werden, kann es auch zu
>Laufzeitunterschieden kommen wenn man den Controller Rechenzeit mässig
>an seine Grenzen bringt. Dann reicht mit hoher Optimierung die
>Geschwindigkeit aus, um zur Abbruchbedingung eine Aufgabe in der
>Schleife schon erfüllt zu haben.Mit niedrigerer Optimierung dann unter
>Umständen nicht mehr.

Das wage ich zu bezweifeln. Da fehlt dann eher irgendwo ein volatile 
oder es ist ein echter, wenn gleich gut verstecker Programmiefehler.

MFG
Falk

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.