Forum: Compiler & IDEs WinAVR-20060125 sprintf bug!?


von Peter (Gast)


Lesenswert?

Ich habe mir meine eigene Library zusammengestellt. U.a. befinden sich
in dieser Lib auch Funktionen für ein VT100-Terminal. Bei einem
Testprogramm ist mir aufgefallen, dass die Funktion sprintf() aus der
stdio nicht funktioniert. Beim compilieren erhalte ich keine
Fehlermeldung oder Warnung. Bei der zweiten Ausgabe auf dem Terminal
(Term_Send_String(buf);) erscheint nur Müll auf dem Monitor. Bitte
testet doch selber mal! Mein C-Quelltext:

#include <avr/io.h>
#include <stdio.h>
#include "M8_Lib.h"

unsigned char buf[100];
unsigned char *s="string";
unsigned char c = '1';
double d = 134.431;
unsigned char i=0;

int main( void )
{
  Term_Initialise();

  for(;;)
  {
    Term_Send_String("char i = ");
    Term_Send_Value_as_Digits(i++);
    Term_Send(0x0d);

    sprintf(buf,"sprintf = %f %c %s \r",d,c,s);
    Term_Send_String(buf);
    wait_500();
    wait_500();
  }
}

Das ist ein Auszug aus der .lss:

...
    sprintf(buf,"sprintf = %f %c %s \r",d,c,s);
  80:  80 91 6c 00   lds  r24, 0x006C
  84:  90 91 6d 00   lds  r25, 0x006D
  88:  9f 93         push  r25
  8a:  8f 93         push  r24
  8c:  80 91 64 00   lds  r24, 0x0064
  90:  99 27         eor  r25, r25
  92:  9f 93         push  r25
  94:  8f 93         push  r24
  96:  80 91 60 00   lds  r24, 0x0060
  9a:  90 91 61 00   lds  r25, 0x0061
  9e:  a0 91 62 00   lds  r26, 0x0062
  a2:  b0 91 63 00   lds  r27, 0x0063
  a6:  bf 93         push  r27
  a8:  af 93         push  r26
  aa:  9f 93         push  r25
  ac:  8f 93         push  r24
  ae:  85 e7         ldi  r24, 0x75  ; 117
  b0:  90 e0         ldi  r25, 0x00  ; 0
  b2:  9f 93         push  r25
  b4:  8f 93         push  r24
  b6:  07 e9         ldi  r16, 0x97  ; 151
  b8:  10 e0         ldi  r17, 0x00  ; 0
  ba:  1f 93         push  r17
  bc:  0f 93         push  r16
  be:  f4 d0         rcall  .+488      ; 0x2a8 <sprintf>

...

??????????
Peter (DF8XA)

: Gesperrt durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was bitte sollen wir denn wie testen?

Sorry, mit einem nicht compilierbaren Schnipsel kann ich leider
nix anfangen.

Ansonsten das Übliche: in 99 % der Fälle sitzt der Bug vor
dem Rechner...

von Peter (Gast)


Lesenswert?

Hallo Jörg,
du wirst doch wohl die Möglichkeit haben, einen String den du mit
sprintf produziert hast, auf irgendein Medium (LCD o.ä.)auszugeben!
73 Peter,DF8XA

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


Lesenswert?

Ja klar.  Nur: bei mir funktioniert's.  Warum auch nicht?

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

linkst du auch das richtige sprintf dazu? Du benötigst die Version mit
Gleitkommaunterstützung.

Matthias

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


Lesenswert?

Selbst wenn er kein Gleitkomma-printf hat, sollte nicht nur
Schrott herauskommen.  Lediglich das %f wird dann in ein
(einzelnes) Fragezeichen gewandelt.

von peter dannegger (Gast)


Lesenswert?

Komisch, bei "UART" und "Müll" denke ich immer an
"RC-Oszillator".

Und fast immer stimmts auch.


Peter

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


Lesenswert?

> Komisch, bei "UART" und "Müll" denke ich immer an
> "RC-Oszillator".

Wenn man ihn nicht richtig benutzt, kann das gut sein.

von Peter (Gast)


Lesenswert?

Danke Matthias. Ja, es lag an der nicht eingebundenen float-Library.
Blöd ist, dass keine Fehlermeldung oder wenigstens eine Warnung beim
compilieren generiert wird. Das sich dabei das Programm von 588 Byte
auf 4632 Byte aufbläht liegt wahrscheinlich daran, dass der Linker die
komplette stdio-Library mit einbindet und nicht nur die für die sprintf
benötigten Funktionen.

@Jörg: Das '?' sieht man aber nur, wenn man ein einzelnes %f in der
Formatanweisung hat. Wenn zusätzlich ein string (%s) und ein char (%c)
in der Formatanweisung stehen, sieht man einfach nur "Müll" auf dem
Monitor und da kannst du dann lange nach deinem einzelnen Fragezeichen
suchen. Andererseits, wenn dich solche Fragen nerven, dann Antworte
doch einfach nicht. Deine Bemerkung, dass bei dir alles funktioniert
bringt niemanden weiter. Das du ja ein "ganz Toller" bist, ist mir
durch deine zahlreichen Beispiele im Umgang mit "Unwissenden" in
diesem Forum längst bekannt. Du solltest besser dein Rufzeichen
weglassen sonst denken die Leute noch alle Funkamateure sind so
"aufgeblasene Besserwisser".

Nochmals danke Matthias
Peter, DF8XA

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


Lesenswert?

> Blöd ist, dass keine Fehlermeldung oder wenigstens eine Warnung beim
> compilieren generiert wird.

Geht leider nicht, da der Compiler nicht weiß, gegen welche Library du
linkst, der Linker aber keine Chance mehr hat, alle Formatstrings zu
überprüfen, ob da nun irgendwo ein Gleitkomma-Format verlangt worden
ist.

> Das sich dabei das Programm von 588 Byte auf 4632 Byte aufbläht
> liegt wahrscheinlich daran, dass der Linker die komplette
> stdio-Library mit einbindet und nicht nur die für die sprintf
> benötigten Funktionen.

Der Linker linkt nur dazu, was gebraucht wird.  Gleitkommarechnung auf
einem 8-Bit-Micro kostet halt richtig.  Da noch dazu printf() immer
den Code für alle möglichen Formate vorhalten muss, bezahlst du ja
auch für andere Dinge wie 32-Bit-Integerzahlen, selbst wenn du sie
nicht benutzt.

> Das '?' sieht man aber nur, wenn man ein einzelnes %f in der
> Formatanweisung hat. Wenn zusätzlich ein string (%s) und ein char
> (%c) in der Formatanweisung stehen, sieht man einfach nur "Müll"
auf
> dem Monitor ...

Dann ist da noch was anderes foul.  Wenn alles Andere bei dir korrekt
eingestellt ist (Taktfrequenz, Baudrate etc.), dann hätte mit
Gleitkommavariante geschrieben werden sollen (z. B., Rundungsfehler
erfinde ich mal schnell frei):

sprintf = 134.430951 1 string <CR>

und mit der Standardversion

sprintf = ? 1 string <CR>

Wenn das bei dir anders war, hast du noch ein weiteres Problem.

> Deine Bemerkung, dass bei dir alles funktioniert bringt niemanden
> weiter.

Deine ungenügende Fehlerbeschreibung allerdings auch nicht.

von Falk W. (dl3daz) Benutzerseite


Lesenswert?

@Jörg
> und mit der Standardversion
> sprintf = ? 1 string <CR>
> Wenn das bei dir anders war, hast du noch ein weiteres Problem.

Wenn ich mich recht erinnere, war es bei mir auch so, daß nach einem
"%f" ohne float-printf nur noch Unsinn ausgegeben wurde. (Nicht die
letzte avr-lib,)

In diesem(!) Punkt stimme ich Peter zu.

Ich werde das morgen nochmal testen und berichten.

73,
Falk

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


Lesenswert?

Hab's eben selbst nochmal ausprobiert.
Ja, mir fällt's jetzt wie Schuppen aus den Haaren... :-)

Das %f wird ja komplett ignoriert, d. h. der Gleitkommawert wird
nicht vom Stack geholt und damit anschließend als char (durch %c)
interpretiert.  Vermutlich habe ich bei derartigen Tests nur ein
%i oder sowas danach gehabt, da wird dann einfach irgendeine Zahl
ausgegeben.

Ich halte das für einen Bug.  Bitte schreibt mal einen Bugreport:

https://savannah.nongnu.org/bugs/?group=avr-libc

Sorry nochmal.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Äääähhhhmmmm Jörg: Haare? verwundertkuck

SCNR² ;-)

Mattias

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


Lesenswert?

:-))

Ein paar sind ja noch da...

von Daniel (Gast)


Lesenswert?

Hallochen

Gibt es eine konstruktive Lösung ?
Habe das gleiche Problem.

Mit
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void main (void) {
  char[10] buffer = "leer";
  float MyFloat = 123.45;
  if (MyFloat == 123.45) sprintf(buffer, "% #3.2f", MyFloat);
}
erhalte ich nur ein Fragezeichen im buffer.

Was muss ich also tun, damit im buffer "123.45" steht ?

Viele Grüsse
Daniel

von Karl H. (kbuchegg)


Lesenswert?

Daniel schrieb:

> Habe das gleiche Problem.
Das glaube ich nicht.

> erhalte ich nur ein Fragezeichen im buffer.

http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio

von Daniel (Gast)


Lesenswert?

Tja, das nützt alles nichts.
Habe alle Options ausprobiert, die da beschrieben sind.
Immer nur Fragezeichen.

Die Lösung habe ich anderswo gefunden:

// sprintf(buffer,"% #3.2f",MyFloat); // DOESN'T WORK --> "?"
dtostrf(MyFloat,7,2,buffer);

Das arbeitet perfekt.

Aber besten Dank ...
Daniel

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


Lesenswert?

Daniel schrieb:
> Gibt es eine konstruktive Lösung ?

Ja: einen eigenen Thread aufmachen für ein neues Thema, statt einen
5 Jahre alten zu kapern.

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.