Forum: Mikrocontroller und Digitale Elektronik sprintf überschreibt RAM-Bereich


von Rainer (Gast)


Lesenswert?

Hallo allerseits!

Ich komm einem Fehler nicht auf die Spur.
Habe einen Puffer deklariert mit 12 Bytes.
Im Programm schreibe ich dann mit der sprintf -Funktion einen
Longwert in diesen Puffer (belegt nur 10Bytes).
Nun passiert es; nach ausführen des sprinf ändern sich Variablen mitten 
im Speicherbereich des RAM.
Warum macht er das denn nur???

Prinzip:

long Wert;     (alles unsigned)
char puffer[12];
char Variable2;
char Variable3;
.
.
char Variable20;
char Variable21;
char Variable22;
.
.
void main (void){
.
alle Variablen auf 0;
.
  for(;;){
  .
  .
  (Variable21 und Variable22 noch OK)
  sprintf(puffer,"=L%06lu\n\r",Wert);
  (hier sind die beiden Variablen mit anderen Werten überschrieben)
  .
  .
  }
}

Ich Benutze deb MSP430F1232.
Programm hat bisher einwandfrei Funktioniert. Erst seit dem ich die
Variablen21 und 22 hinzugefügt habe tritt dieser Fehler auf.
Der Compiler sagt, dass erst 141 Byte des RAM belegt sind.
Der MSP hat 256Byte RAM.

Vielleicht hat jemand 'ne Idee.

Schönen Tag noch!

Gruß Rainer

von ARM-Fan (Gast)


Lesenswert?

Nur mal so allgemein ins Blaue geraten:
Kommt dir vielleicht der Stack "von hinten" schon entgegen?

von Rainer (Gast)


Lesenswert?

Hallo ARM-Fan!

Glaube nicht!
Das dachte ich zuerst auch. Hab dann vor dem Programmstart den 
kompletten RAM     auf 0 gesetzt. Nach dem Fehler sind die Bytes 
zwischen diesen Variablen und dem Stack unverändert auf 0.
Gut nicht wirklich alle. Von der Variablen-Seite her ändern sich noch 
5-6 Bytes. Das Verstehe ich auch schon nicht. Dachte mir einfach, den 
Platz nimmt der Compiler irgenwie her, da dort keine Variablen 
angesiedelt sind.
Aber die beiden oben genannten Variablen sind ja deklariert, und können 
doch eigentlich nicht wegoptimiert werden.

ODER?

Trotzdem Danke für die schnelle Antwort, das ging ja flott!!

Rainer

von Rainer (Gast)


Lesenswert?

Die sprintf soll ja ziemlich speicherhungrig sein.
Sollte man auf diese Funktion auf relativ kleinen µC besser verzichten?
Wie gesagt, mein µC hat 256 Bytes. Davon sind laut Compiler 141 belegt.
Da sollte aber doch eigentlich noch Platz vorhanen sein? ODER?

von crazy horse (Gast)


Lesenswert?

sprintf erwartet nicht die Variable selbst, sondern einen Zeiger auf die 
Variable.
int sprintf(char *buffer, const char *format[, argument, ...]);

von Dirk D. (dirkd)


Lesenswert?

> sprintf erwartet nicht die Variable selbst, sondern einen Zeiger auf die
> Variable.

Nein

> int sprintf(char *buffer, const char *format[, argument, ...]);

Da steht:
1. Argument Zeiger auf einen Buffer in den der String geschrieben werden 
soll
=> puffer

2. Zeiger auf einen String der beschreibt wie der String aussehen soll
=> ,"=L%06lu\n\r",

3. optional weitere Parameter
In diesem Fall Wert.

Genau wie bei printf. Das sieht im Code gut aus.

Wie groß ist eigentlich Wert in diesem Beispiel? Wenn die Zahl mehr als 
6 Dezimalstellen groß ist, langen die 12 Byte für puffer nicht und die 
nachfolgenden Speicherstellen werden überschrieben.

von Karl H. (kbuchegg)


Lesenswert?

Die häufigste Ursache für solches Verhalten ist es,
wenn der aufnehmende String-Buffer zu klein dimensioniert
ist.

Daher die Frage: Da oben, ist das realer Code oder
ist das ein Beispiel, welches für das Forum konstruiert
wurde?

Zähl mal den Formatstring ab, wieviele Zeichen da
tatsächlich generiert werden. Berücksichtige auch,
dass Formatangaben wie %06lu durchaus auch mehr als
6 Zeichen liefern können (wenn die Zahl mit 6 Ziffern
nicht darstellbar ist, wird das Feld eigenmächtig vergrößert).

von Rainer (Gast)


Lesenswert?

OK.
Aber darauf habe ich doch keinen Einfluss. Oder?

Mit
sprintf(puffer,"=L%06lu\n\r",Wert);
gebe ich doch eigentlich den Wert an;
Verstehe ich da was falsch? Wie soll ich das anderst machen, als die 
Variable zu definieren, und sie dann der sprinf zu übergeben.

Oder muss ich da erst einen Zeiger anlegen, und diesen auf den Wert 
zeigen lassen?

von Rainer (Gast)


Lesenswert?

ups!
das hat zu lange gedauert.
Vergesst meinen letzten Beitrag.

von crazy horse (Gast)


Lesenswert?

und dann gibts da noch die Probleme mit long-Werten, standardmässig 
arbeiten viele Compiler für MCs erstmal nur mit int, um (s)printf() 
grössenmässig nicht zu sehr aufzublähen. Um welchen Compiler gehts 
überhaupt? Compileroptions?

von Peter D. (peda)


Lesenswert?

Rainer wrote:

> Mit
> sprintf(puffer,"=L%06lu\n\r",Wert);
> gebe ich doch eigentlich den Wert an;


Du gibst damit nur die minimale Länge an.

Für long mußt Du immer mindestens 11 (signed: 12) Bytes reservieren.


Peter

von Rainer (Gast)


Lesenswert?

@ crazy horse
Arbeite mit dem IAR-Compiler.
Das printf-Format ist hier auf Medium gestellt (no float).
Library ist die clib.

@peter dannegger
OK; Werd ich berücksichtigen.

von Rainer (Gast)


Lesenswert?

Habs jetzt mal mit einer Puffergröße von 20 Byte probiert 
(sicherheitshalber), und den Puffer ans Ende der Variablendeklaration 
gelegt.

Genau der gleiche Fehler.
Immer verschreibt die sprintf den RAM-Speicher ab der Adresse 0x23C.
Diesmal eben den Puffer ab Puffer[16].

von Gast (Gast)


Lesenswert?

Setz doch mal die Deklaration "char puffer[12];" ans Ende der 
Variablendeklarationen. Nicht dass ich wüßte, was das für Auswirkungen 
haben wird, aber vielleicht bringt es irgenwelche neuen Einsichten 
(alles funktioniert: nicht so gut, weil Ursache immer noch unklar / 
Absturz: Code hinter puffer wurde tatsächlich überschrieben).

von Rainer (Gast)


Lesenswert?

Hab ich schon.

Siehe ein Beitrag zuvor, mit "char puffer[20];"
Es überschreibt mir die letzten stellen vom Puffer
(Puffer[16],Puffer[17],Puffer[18],Puffer[19]).
Wieder ab der Adresse 0x23C; wie zuvor.

von Gast (Gast)


Lesenswert?

>Hab ich schon.

Jetzt seh ich's. Ausserdem hatte ich einen Denkfehler, dass die 
Variablen vor dem Code liegen. Bin kein AVR-Nutzer, aber falls es die 
malloc-Funktion gibt, versuch's mal damit.

von Rainer (Gast)


Lesenswert?

malloc?

OK; malloc ist zum Speicher reservieren da. Aber wie soll ich das
hier verwenden?

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.