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
Nur mal so allgemein ins Blaue geraten: Kommt dir vielleicht der Stack "von hinten" schon entgegen?
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. int sprintf(char *buffer, const char *format[, argument, ...]);
> 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?
ups! das hat zu lange gedauert. Vergesst meinen letzten Beitrag.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.