WinAVR-20060125 sprintf bug!?

Gast #363213
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)
Gast #363221
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
Moderator Persönliche Seite #363222
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.
Persönliche Seite #363223
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
Moderator Persönliche Seite #363224
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.
Gast #2214840
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
Gast #2214942
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
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.