Cosa succede se si verifica un errore di runtime?


17

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:


21

Innanzitutto, vediamo alcuni esempi di cosa può andare storto.

Variabili locali non inizializzate

void setup() {
  int status;
  pinMode(13, OUTPUT);
  digitalWrite(13, status);
} 

Come sottolineato da Edgar Bonet nei commenti, le variabili locali come statusnel 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.

Fonte: Manuale di riferimento di AVR Libc - Domande frequenti - Non dovrei inizializzare tutte le mie variabili?

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.

Overflow di memoria

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.

Vai a un'istruzione illegale

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.

Altre cose brutte che possono accadere

Bene, puoi rimanere senza RAM, per esempio. Cos'altro. In ogni caso, penso che il tuo programma continuerà a funzionare, probabilmente non come previsto.

Tipi di protezione

Nei sistemi informatici, problemi come questi di solito vengono affrontati a vari livelli:

  1. Dal compilatore
  2. Dal runtime del linguaggio di programmazione (come ad esempio in Java).
  3. Dal sistema operativo o dal processore (se la tua memoria accede a una posizione al di fuori dei confini dello spazio degli indirizzi riservato al tuo programma, il sistema operativo o il processore potrebbero disporre di meccanismi di sicurezza per impedirlo)

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.

Le risposte

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).


1
Grande! La migliore risposta che ho visto su Arduino.SE finora!
The Guy with The Hat,

1
Grazie!! Penso che dovremmo sforzarci di dare grandi risposte il più possibile. Ma mi preoccupa un po 'il fatto che non abbiamo così tanti ESPERTI EE REALI che potrebbero guardare risposte come la mia e trovare errori evidenti. In realtà, questo è il motivo per cui ho pubblicato la risposta anche se non so molto sugli MCU AVR. Questo per vedere se troviamo qualcuno che lo corregga. Di certo non vogliamo che i pennoni intelligenti come me dicano cose che non vanno bene e se ne vadano. Ma questa è probabilmente una discussione per il sito Meta.
Ricardo,

5
@Ricardo - Un commento che vorrei fare è che le variabili non esplicitamente inizializzate non sono necessariamente non inizializzate. Le variabili definite al di fuori delle funzioni hanno generalmente la cosiddetta "durata di memorizzazione automatica", che viene quindi inizializzata per default a zero. Vedi en.cppreference.com/w/cpp/language/default_initialization per maggiori informazioni. Il comportamento di inizializzazione è abbastanza complesso che probabilmente è pericoloso fare affidamento, ma fare affermazioni generali non è probabilmente una grande idea.
Connor Wolf,

1
Inoltre, la SRAM viene inizializzata su 0 al ripristino o all'avvio, quindi puoi fare alcune ipotesi informate sulle variabili non inizializzate, se vuoi vivere pericolosamente. Non dovresti fare affidamento su questo comportamento, ma è interessante.
Connor Wolf,

1
C'è un esempio interessante di ciò che accade quando si esaurisce SRAM qui: electronics.stackexchange.com/questions/42049/… . Fondamentalmente, lo stack blocca parte dell'heap, o viceversa. Questo può fare cose interessanti come corrompere alcune parti dello stack-frame (ritorna la funzione di interruzione, ecc.) O scrivere dati non validi su variabili.
Connor Wolf,

9

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 .


6

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


5

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.


3

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.


-2

Arduino si riavvierà (ovvero riavvierà setup()e loop()).


1
Non necessariamente. Un errore di runtime potrebbe far sì che il programma vada in loop senza riavviare.
Nick Gammon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.