Was passiert, wenn in einem Programm ein Laufzeitfehler auftritt? Wird die Ausführung des Programms einfach gestoppt? Kann ich das Arduino irgendwie dazu bringen, mir den Fehler zu erklären?
Lassen Sie uns zunächst einige Beispiele dafür sehen, was schief gehen kann.
void setup() {
int status;
pinMode(13, OUTPUT);
digitalWrite(13, status);
}
Wie von Edgar Bonet in den Kommentaren ausgeführt, werden lokale Variablen wie status
im obigen Code vom C ++ - Compiler nicht implizit initialisiert. Das Ergebnis des obigen Codes ist also unbestimmt. Um dies zu vermeiden, stellen Sie sicher, dass Sie Ihren lokalen Variablen immer Werte zuweisen.
Bei globalen und statischen Variablen sieht es etwas anders aus:
Globale und statische Variablen werden vom C-Standard garantiert auf 0 initialisiert.
Das heißt, Sie sollten sich keine Gedanken darüber machen, sie in Ihrem Code auf 0 zu initialisieren. In der Tat sollten Sie es wirklich vermeiden, da die Initialisierung Speicher verschwenden kann. Initialisieren Sie sie nur mit anderen Werten als 0.
int array[10];
int v = array[100];
array[-100] = 10;
Das erste Problem hier ist, dass Sie nicht wissen, was v zugewiesen wird, aber schlimmer ist, dass Sie nicht wissen, was Sie mit der Zuweisung zu Position -100 von falsch gemacht haben array
.
void doSomething( void ) {
for (int i = 0; i < 1000; i++);
}
void setup ()
{
void (*funcPtr)( void );
funcPtr = &doSomething;
funcPtr(); // calls doSomething();
funcPtr = NULL;
funcPtr(); // undefined behavior
}
Der erste Anruf an funcPtr()
wird tatsächlich ein Anruf an sein doSomething()
. Anrufe wie der zweite können zu undefiniertem Verhalten führen.
Zum Beispiel kann Ihnen der Arbeitsspeicher ausgehen. Was sonst. Ich denke auf jeden Fall, dass Ihr Programm weiterhin ausgeführt wird, wahrscheinlich nicht so, wie Sie es beabsichtigt haben.
In Computersystemen werden Probleme wie diese normalerweise auf verschiedenen Ebenen behandelt:
Arduinos haben nur eingeschränkten Schutz für den Compiler und wahrscheinlich auch nichts anderes. Die gute Nachricht ist, dass sie nicht für mehrere Aufgaben eingesetzt werden. Das einzige betroffene Programm ist Ihr Programm. In jedem Fall führt einer dieser Fehler zu einem fehlerhaften Verhalten.
Die Annahmen sind alle Probleme, die ich oben angegeben habe, sind Laufzeitprobleme.
Was passiert, wenn in einem Programm ein Laufzeitfehler auftritt?
Das Programm wird fortgesetzt und was passiert, hängt von den Nebenwirkungen des Laufzeitfehlers ab. Ein Aufruf des Nullfunktionszeigers lässt das Programm wahrscheinlich an eine unbekannte Stelle springen.
Wird die Ausführung des Programms einfach gestoppt?
Nein, es wird so weitergehen, als wäre nichts Außergewöhnliches passiert, wahrscheinlich tun, was Sie nicht beabsichtigt hatten. Es kann sich zurücksetzen oder unregelmäßig handeln. Es kann einige Eingänge in Ausgänge verwandeln und einen oder zwei Sensoren verbrennen (aber das ist höchst unwahrscheinlich ).
Gibt es eine Möglichkeit, dass der Arduino mir sagt, was der Fehler ist?
Ich glaube nicht. Wie ich bereits sagte, sind die Schutzmechanismen nicht vorhanden. Es gibt keine Laufzeitunterstützung durch die Sprache, kein Betriebssystem, keine Hardwareprüfungen auf Speicherzugriff außerhalb der Grenzen (der Bootloader zählt auch nicht dazu). Sie müssen nur vorsichtig mit Ihrem Programm sein und wahrscheinlich Ihre eigenen Sicherheitsnetze einrichten.
Der Grund für den fehlenden Schutz liegt wahrscheinlich darin, dass Arduino-Controller zu billig sind, zu wenig Arbeitsspeicher haben und nichts zu Wichtiges ausführen sollten (ja, es scheint einen Haftungsausschluss von AVR zu geben, damit Sie die normalerweise von AVR verwendeten MCUs nicht verwenden können Arduino in Lebenserhaltungssystemen).
Es gibt keine Laufzeitausnahmen. Es gibt nur undefiniertes Verhalten.
Wirklich, es gibt keine Ausnahmen überhaupt . Wenn Sie versuchen, einen ungültigen Vorgang auszuführen, sind die Ergebnisse unbekannt.
Es gibt überhaupt keine Laufzeitüberprüfung, außer dem, was Sie implementieren. Ihr Programm läuft auf Bare-Metal-Hardware. Es ist das Desktop-Äquivalent zu Ring-0 , da der ATmega keine Ringe hat .
quelle
Es gibt einen Mechanismus, mit dem die MCU aus dem fehlerhaften Zustand gebracht werden kann, und es handelt sich um den Watchdog-Timer . Wenn Sie Code implementieren, der wiederholt in einer Schleife ausgeführt wird und der nicht länger als eine festgelegte Zeit ausgeführt wird, können Sie diese Zeit als Überwachungszeitraum festlegen und den Timer aktivieren.
Dann müssen Sie den Timer in der Schleife wiederholt zurücksetzen. Wenn Ihr Code in einer Bedingungsschleife einfriert, die niemals endet, zählt der Watchdog auf Null und setzt schließlich die MCU zurück.
Auf diese Weise verlieren Sie Daten, aber wenn Sie den AVR WDT im Interrupt-Modus ausführen, können Sie einige Daten speichern, bevor Sie die MCU zurücksetzen.
So kann der Watchdog-Timer Ihren Code vor gelegentlichen unbeabsichtigten Endlosschleifen schützen.
Dokumentation: AVR132: Verwenden des erweiterten Watchdog-Timers
quelle
Sie benötigen einen Hardware-Debugger für so etwas. In der Regel verhält sich das Programm jedoch nicht so, wie Sie es erwarten, und Sie müssen sich diesen Codeabschnitt ansehen, um das Problem zu identifizieren.
Eine übliche / schnelle / einfache Möglichkeit, dies zu tun, besteht darin, print-Anweisungen hinzuzufügen, um die Werte von Variablen oder irgendetwas anderem auszudrucken, damit Sie wissen, dass das Programm problemlos an diesen Punkt im Code gelangt. Auf diese Weise können Sie das Problem weiter eingrenzen.
Ich glaube, VisualMicro hat einige Debugging-Funktionen eingebaut.
quelle
Ich würde annehmen, dass die AVR-CPU keine Fehlererkennungs- oder Wiederherstellungstools hat. Es kann einfach aufhören oder den Fehler und die Konsequenzen ignorieren. Wie Sachleen sagte, sollten Sie einige Debug-Anweisungen in Ihr Programm einfügen, die Daten während eines Vorgangs ausdrucken, um zu testen, ob sie funktionieren. Wenn Sie ein Emulaor verwenden und Haltepunkte setzen, können Sie leicht ein Problem finden.
quelle
Das Arduino wird neu gestartet (dh es wird neu gestartet
setup()
undloop()
).quelle