PIC18F2550 Schleifenzähler von sprintf überschrieben

Ich habe den folgenden Code mit dem MPLab- und XC8-Compiler von Microchip kompiliert und auf einem PIC18F2550 ausgeführt, der etwas ziemlich Seltsames macht:

char output[20];
int i = 0;

char currentStatus = readShiftReg();
for (i = 0; i < 8; i++) {
    if ((currentStatus & (1 << i)) == (1 << i))
        sprintf(output, "Sensor %d is currently on \r\n", i + 1);
    else
        sprintf(output, "Sensor %d is currently off \r\n", i + 1);
    putsUSART(output);
}    

Die for-Schleife wird immer nur einmal durchlaufen und während dieser einen Iteration wird die zweite korrekt ausgeführt sprintf, aber nachdem sie ausgeführt wurde, iist der Wert von zufällig (26154, 8294, ...). Ich habe versucht, am Anfang der Schleife igegen eine andere Variable auszutauschen, die den Wert von jzuweist , aber das Gleiche passiert immer noch mit .iji

Es scheint, als wäre es etwas mit sprintf, denn wenn ich den Debugger verwende, iwird der Wert von erst nach den Läufen geändert sprint. Eine Sache, die zu beachten ist, ist, dass der Wert in der Ausgabe korrekt ist (dh "Sensor 0 ist derzeit aus \r\n"), was dies noch verwirrender macht.

Dies sollte ein sehr einfacher Code sein, aber er funktioniert nicht und ich bin sicher, dass es eine einfache Erklärung gibt. Wo soll ich suchen?

Antworten (2)

Dein Problem ist diese Zeile:

char output[20];

Sie weisen dem Puffer 20 Zeichen für Ihre Zeichenfolge zu und rufen dann sprintf() auf, um ihn zu füllen.

Ihre Formatzeichenfolge ist jedoch zu lang, noch bevor der Dezimalwert enthalten ist. Denken Sie daran, dass das letzte Array-Element immer (ein NUL-Zeichen) sein muss, \x00Sie haben 19 Zeichen für Ihre Nachricht.

Zählen Sie die Anzahl der Zeichen in dieser Zeichenfolge:

Sensor %d ist derzeit ausgeschaltet \r\n

Es gibt 29 Zeichen (unter der Annahme einer zweistelligen Zahl). Dies führt zu einem Pufferüberlauf, der andere Variablen überlastet und dazu führen kann, dass Ihr Programm auf unerwartete Weise arbeitet. Es ist eine häufige Art von Sicherheitsproblem in C.

Erhöhen Sie die Größe Ihres Puffers, sodass er groß genug ist, um Folgendes aufzunehmen:

  • alle festen Buchstaben aus Ihrer Nachricht.
  • die größte Zahl, die die Variable ijemals enthalten wird.
  • das nachlaufende \r\n.
  • das abschließende NUL-Byte.
doh... Ich wusste, dass es etwas Einfaches sein würde. Danke!
Wenn Ihr Compiler dies unterstützt, bevorzugen Sie außerdem snprintf() gegenüber sprintf().

Ihre char outputDeklaration ist zu klein für die Zeichenfolge, in die Sie schreiben möchten.

Probier es nochmal mitchar output[50]

Ihre Zählvariable iwird direkt hinter der letzten Variablen des Char-Arrays gespeichert.

Etwas wie das:

Adress       Value
0x0F00      char[0]
0x0F01      char[1]
  .           .
  .           .
  .           .
0x0F19      char[19]   <-- last variable of char
0x0F20      i          <-- counter variable

Jetzt überprüft sprintf nicht die Länge des Arrays, in das es schreibt. Überprüfen Sie die Länge des Arrays, bevor Sie es in Code schreiben!

zwei perfekte Antworten, ich wünschte, ich könnte beide als akzeptierte Antwort markieren.