mikrocontroller.net

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


Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ARM-Fan (Gast)
Datum:

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

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: crazy horse (Gast)
Datum:

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

Autor: Dirk Dörr (dirkd)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups!
das hat zu lange gedauert.
Vergesst meinen letzten Beitrag.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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].

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
malloc?

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.