Cosa succede se si verifica un errore di runtime in un programma? L'esecuzione del programma si interromperà? C'è un modo in cui ottengo che Arduino mi dica qual è l'errore?
Cosa succede se si verifica un errore di runtime in un programma? L'esecuzione del programma si interromperà? C'è un modo in cui ottengo che Arduino mi dica qual è l'errore?
Risposte:
Innanzitutto, vediamo alcuni esempi di cosa può andare storto.
void setup() {
int status;
pinMode(13, OUTPUT);
digitalWrite(13, status);
}
Come sottolineato da Edgar Bonet nei commenti, le variabili locali come status
nel codice sopra non vengono inizializzate implicitamente dal compilatore C ++. Quindi, il risultato del codice sopra è indeterminato. Per evitarlo, assicurati di assegnare sempre valori alle variabili locali.
Le cose sono leggermente diverse con variabili globali e statiche:
Le variabili globali e statiche sono garantite per essere inizializzate su 0 dallo standard C.
Ciò significa che non dovresti preoccuparti di inizializzarli su 0 nel tuo codice. In effetti, dovresti davvero evitarlo, poiché l'inizializzazione potrebbe sprecare memoria. Inizializzarli solo su valori diversi da 0.
int array[10];
int v = array[100];
array[-100] = 10;
Il primo problema qui è che non sai cosa verrà assegnato a v, ma peggio è che non sai cosa hai incasinato con l'incarico nella posizione -100 di 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
}
La prima chiamata a funcPtr()
sarà effettivamente una chiamata a doSomething()
. Chiamate come la seconda possono portare a comportamenti indefiniti.
Bene, puoi rimanere senza RAM, per esempio. Cos'altro. In ogni caso, penso che il tuo programma continuerà a funzionare, probabilmente non come previsto.
Nei sistemi informatici, problemi come questi di solito vengono affrontati a vari livelli:
Gli Arduinos hanno solo una protezione limitata del compilatore, e probabilmente nient'altro. La buona notizia è che non sono multitasking, quindi l'unico programma interessato è il tuo. In ogni caso, uno qualsiasi di questi bug porterà a comportamenti irregolari.
I presupposti sono tutti i problemi che ho indicato sopra sono problemi di runtime.
Cosa succede se si verifica un errore di runtime in un programma?
Il programma continuerà e ciò che accadrà dipenderà dagli effetti collaterali dell'errore di runtime. Una chiamata al puntatore a funzione null probabilmente farà saltare il programma in una posizione sconosciuta.
L'esecuzione del programma si interromperà?
No, continuerà come se non fosse successo nulla di straordinario, probabilmente facendo ciò che non avevi intenzione di fare. Potrebbe ripristinare o agire in modo irregolare. Potrebbe trasformare alcuni ingressi in uscite e bruciare un sensore o due (ma è altamente improbabile ).
C'è un modo per convincere Arduino a dirmi qual è l'errore?
Io non la penso così. Come ho detto prima, i meccanismi di protezione non esistono. Non esiste alcun supporto di runtime dalla lingua, nessun sistema operativo, nessun controllo hardware per l'accesso alla memoria fuori limite (il bootloader non conta neanche come). Devi solo stare attento con il tuo programma e probabilmente impostare le tue reti di sicurezza.
Il motivo della mancanza di protezione è probabilmente dovuto al fatto che i controller Arduino sono troppo economici, hanno memoria insufficiente e non dovrebbero eseguire nulla di troppo importante (sì, sembra che ci sia un disclaimer da parte di AVR da qualche parte per non utilizzare gli MCU normalmente utilizzati da Arduino nei sistemi di supporto vitale).
Non ci sono eccezioni di runtime. C'è solo un comportamento indefinito.
In realtà, non ci sono eccezioni a tutti . Se si tenta di eseguire un'operazione non valida, i risultati saranno sconosciuti.
Non esiste alcun controllo di runtime, ad eccezione di ciò che si implementa. Il programma è in esecuzione su hardware bare metal. È l'equivalente desktop di funzionare sempre in ring-0 , perché ATmega non ha anelli .
Esiste un meccanismo che può ottenere MCU da uno stato irregolare ed è il timer del watchdog . Se stai implementando del codice che verrà eseguito ripetutamente in un ciclo, che non verrà eseguito in qualsiasi momento più a lungo di un tempo fisso, puoi impostare questo periodo come periodo di controllo e abilitare il timer.
Quindi, è necessario reimpostare ripetutamente il timer nel loop. Se il tuo codice si blocca in un ciclo di condizioni che non finirà mai, il watchdog conterà a zero e alla fine ripristinerà l'MCU.
In questo modo si stanno perdendo dati, ma se si esegue AVR WDT in modalità di interruzione, è possibile memorizzare alcuni dati prima di ripristinare l'MCU.
Quindi il timer del watchdog può proteggere il tuo codice da loop infiniti involontari occasionali.
Documentazione: AVR132: Utilizzo del timer watchdog avanzato
Avresti bisogno di un debugger hardware per qualcosa del genere. Ma di solito vedrai che il programma non si comporterà come ti aspetti e dovrà guardare quella sezione del codice per identificare il problema.
Un modo comune / rapido / semplice per farlo è quello di aggiungere istruzioni di stampa per stampare i valori delle variabili o qualsiasi altra cosa in modo da sapere che il programma arriva a quel punto nel codice senza problemi. Questo ti aiuterà a isolare ulteriormente il problema.
Credo che VisualMicro abbia alcune funzionalità di debug integrate.
Suppongo che la CPU AVR non abbia strumenti di rilevamento o recupero degli errori. Potrebbe semplicemente smettere o andare avanti ignorando l'errore e le conseguenze. Come ha detto Sachleen, è necessario aggiungere alcune istruzioni di debug nel programma che stampano i dati nel mezzo di un'operazione, per verificare se funziona. Se usi un emulaor e imposti dei punti di interruzione, potresti facilmente trovare un problema.
Arduino si riavvierà (ovvero riavvierà setup()
e loop()
).