Co się stanie, jeśli w programie wystąpi błąd czasu wykonywania? Czy wykonanie programu się po prostu zatrzyma? Czy jest jakiś sposób, aby skłonić Arduino do powiedzenia mi, jaki jest błąd?
Co się stanie, jeśli w programie wystąpi błąd czasu wykonywania? Czy wykonanie programu się po prostu zatrzyma? Czy jest jakiś sposób, aby skłonić Arduino do powiedzenia mi, jaki jest błąd?
Odpowiedzi:
Najpierw zobaczmy kilka przykładów tego, co może pójść nie tak.
void setup() {
int status;
pinMode(13, OUTPUT);
digitalWrite(13, status);
}
Jak zauważył Edgar Bonet w komentarzach, zmienne lokalne, takie jak status
w powyższym kodzie, nie są domyślnie inicjowane przez kompilator C ++. Tak więc wynik powyższego kodu jest nieokreślony. Aby tego uniknąć, upewnij się, że zawsze przypisujesz wartości do zmiennych lokalnych.
W przypadku zmiennych globalnych i statycznych sytuacja wygląda nieco inaczej:
Gwarantuje się, że zmienne globalne i statyczne zostaną zainicjowane do wartości 0 przez standard C.
Oznacza to, że nie powinieneś się martwić o zainicjowanie ich na 0 w swoim kodzie. W rzeczywistości powinieneś tego unikać, ponieważ inicjalizacja może marnować pamięć. Zainicjuj je tylko na wartości inne niż 0.
int array[10];
int v = array[100];
array[-100] = 10;
Pierwszym problemem jest to, że nie wiesz, co zostanie przypisane do v, ale gorsze jest to, że nie wiesz, co pomyliłeś przy przypisaniu do pozycji -100 z 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
}
Pierwsze połączenie do funcPtr()
będzie faktycznie połączeniem z doSomething()
. Połączenia takie jak drugie mogą prowadzić do nieokreślonego zachowania.
Na przykład możesz zabraknąć pamięci RAM. Co jeszcze. W każdym razie myślę, że twój program będzie działał, prawdopodobnie nie w zamierzony sposób.
W systemach komputerowych takie problemy są zazwyczaj rozwiązywane na różnych poziomach:
Arduinos mają tylko ograniczoną ochronę kompilatora i prawdopodobnie nic więcej. Dobrą wiadomością jest to, że nie są wielozadaniowe, więc dotyczy to tylko twojego programu. W każdym razie każdy z tych błędów spowoduje nieprawidłowe zachowanie.
Założenia są tymi wszystkimi problemami, które wskazałem powyżej, są problemami w czasie wykonywania.
Co się stanie, jeśli w programie wystąpi błąd czasu wykonywania?
Program będzie kontynuowany, a to, co się stanie, będzie zależeć od skutków ubocznych błędu czasu wykonywania. Wywołanie wskaźnika funkcji zerowej prawdopodobnie spowoduje, że program przeskoczy w nieznane miejsce.
Czy wykonanie programu się po prostu zatrzyma?
Nie, będzie tak, jakby nic nadzwyczajnego się nie wydarzyło, prawdopodobnie robiąc to, czego nie zamierzałeś. Może się zresetować lub działać nieprawidłowo. Może przekształcić niektóre wejścia w wyjścia i spalić czujnik lub dwa (ale jest to bardzo mało prawdopodobne ).
Czy jest jakiś sposób, aby Arduino powiedział mi, jaki jest błąd?
Nie wydaje mi się Jak powiedziałem wcześniej, mechanizmów ochronnych nie ma. Język nie obsługuje środowiska uruchomieniowego, nie ma systemu operacyjnego, nie sprawdza sprzętu pod kątem dostępu do pamięci poza zakresem (bootloader nie jest również liczony). Musisz tylko uważać na swój program i prawdopodobnie ustawić własne sieci bezpieczeństwa.
Przyczyną braku ochrony jest prawdopodobnie to, że kontrolery Arduino są zbyt tanie, mają za mało pamięci i nie powinny uruchamiać niczego zbyt ważnego (tak, wydaje się, że AVR zrzeka się gdzieś, aby nie używać MCU normalnie używanych przez Arduino w systemach podtrzymywania życia).
Nie ma wyjątków czasu wykonywania. Istnieje tylko niezdefiniowane zachowanie.
Naprawdę, nie ma wyjątków w ogóle . Jeśli spróbujesz wykonać niepoprawną operację, jej wyniki będą nieznane.
W ogóle nie ma sprawdzania środowiska wykonawczego, z wyjątkiem tego , co implementujesz. Twój program działa na sprzęcie typu bare-metal. Jest to komputerowy odpowiednik ciągłego działania w pierścieniu 0 , ponieważ ATmega nie ma dzwonków .
Istnieje jeden mechanizm, który może uzyskać MCU ze stanu nieregularnego i jest to zegar nadzorujący . Jeśli implementujesz jakiś kod, który wielokrotnie będzie działał w pętli, który nie będzie działał dłużej niż jakiś ustalony czas, możesz ustawić ten czas jako okres nadzoru i włączyć timer.
Następnie musisz wielokrotnie resetować stoper w pętli. Jeśli kod zawiesi się w pętli warunku, która nigdy się nie skończy, wówczas watchdog policzy do zera i ostatecznie zresetuje MCU.
W ten sposób tracisz dane, ale jeśli uruchomisz AVR WDT w trybie przerwania, możesz zapisać niektóre dane przed zresetowaniem MCU.
Tak więc zegar nadzoru może chronić Twój kod przed okazjonalnymi niezamierzonymi niekończącymi się pętlami.
Dokumentacja: AVR132: Korzystanie z ulepszonego timera nadzoru
Potrzebujesz czegoś takiego jak debugger sprzętowy. Zazwyczaj jednak program nie działa tak, jak tego oczekujesz, i musisz spojrzeć na tę sekcję kodu, aby zidentyfikować problem.
Typowym / szybkim / łatwym sposobem na to jest dodanie instrukcji print, aby wydrukować wartości zmiennych lub cokolwiek innego, abyś wiedział, że program bez problemu dotrze do tego miejsca w kodzie. Pomoże to w dalszej izolacji problemu.
Wierzę, że VisualMicro ma wbudowane funkcje debugowania.
Zakładam, że procesor AVR nie ma żadnych narzędzi do wykrywania błędów ani odzyskiwania. Może po prostu przestać lub ignorować błąd i konsekwencje. Jak powiedział sachleen, powinieneś dodać do swojego programu kilka instrukcji debugowania, które drukują dane w trakcie operacji, aby sprawdzić, czy działa. Jeśli używasz emulatora i ustawiasz punkty przerwania, możesz łatwo znaleźć problem.
Arduino zrestartuje (czyli będzie to ożywienie setup()
i loop()
).