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
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
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?
> 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.
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).
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?
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?
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
@ 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.
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].
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).
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.
>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.