O que acontece se houver um erro de tempo de execução?

17

O que acontece se houver um erro de tempo de execução em um programa? A execução do programa será interrompida? Existe alguma maneira de obter o Arduino para me dizer qual é o erro?

O cara com o chapéu
fonte

Respostas:

21

Primeiro, vamos ver alguns exemplos do que pode dar errado.

Variáveis ​​locais não inicializadas

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

Conforme apontado por Edgar Bonet nos comentários, variáveis ​​locais como statusno código acima não são implicitamente inicializadas pelo compilador C ++. Portanto, o resultado do código acima é indeterminado. Para evitar isso, certifique-se de sempre atribuir valores às suas variáveis ​​locais.

As coisas são um pouco diferentes com variáveis ​​globais e estáticas:

Variáveis ​​globais e estáticas são garantidas para serem inicializadas em 0 pelo padrão C.

Fonte: Manual de referência do AVR Libc - Perguntas freqüentes - Não devo inicializar todas as minhas variáveis?

Isso significa que você não deve se preocupar em inicializá-los para 0 no seu código. De fato, você realmente deve evitá-lo, pois a inicialização pode desperdiçar memória. Inicialize-os apenas com valores diferentes de 0.

Excesso de memória

int array[10];
int v = array[100];
array[-100] = 10;

O primeiro problema aqui é que você não sabe o que será designado para v, mas o pior é que você não sabe o que errou com a atribuição para a posição -100 de array.

Ir para uma instrução ilegal

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
}

A primeira chamada para funcPtr()realmente será uma chamada para doSomething(). Chamadas como a segunda podem levar a um comportamento indefinido.

Outras coisas ruins que podem acontecer

Bem, você pode ficar sem memória RAM, por exemplo. O quê mais. De qualquer forma, acho que seu programa continuará sendo executado, provavelmente não da maneira que você pretendia.

Tipos de proteção

Em sistemas de computadores, problemas como esses geralmente são tratados em vários níveis:

  1. Pelo compilador
  2. Pelo tempo de execução da linguagem de programação (como em Java, por exemplo).
  3. Pelo sistema operacional ou pelo processador (se sua memória acessar uma posição fora dos limites do espaço de endereço reservado ao seu programa, o SO ou o processador poderá ter mecanismos de segurança para impedir isso)

Os Arduinos têm apenas uma proteção limitada do compilador e provavelmente nada mais. A boa notícia é que eles não são multitarefas; portanto, o único programa afetado é o seu. De qualquer forma, qualquer um desses erros levará a um comportamento errático.

As respostas

As suposições são todos os problemas que afirmei acima são problemas de tempo de execução.

O que acontece se houver um erro de tempo de execução em um programa?

O programa continuará e o que acontecerá dependerá dos efeitos colaterais do erro de tempo de execução. Uma chamada para o ponteiro de função nula provavelmente fará o programa pular para um local desconhecido.

A execução do programa será interrompida?

Não, continuará como se nada extraordinário tivesse acontecido, provavelmente fazendo o que você não pretendia. Pode redefinir ou agir de forma irregular. Pode transformar algumas entradas em saídas e queimar um sensor ou dois (mas isso é altamente improvável ).

Existe alguma maneira de obter o Arduino para me dizer qual é o erro?

Acho que não. Como eu disse anteriormente, os mecanismos de proteção não estão lá. Não há suporte de tempo de execução do idioma, nem sistema operacional, nem verificações de hardware para acesso à memória fora dos limites (o carregador de inicialização também não conta). Você só precisa ter cuidado com o seu programa e provavelmente definir suas próprias redes de segurança.

O motivo da falta de proteção é provavelmente porque os controladores do Arduino são muito baratos, têm pouca memória e não devem executar nada muito importante (sim, parece haver um aviso de isenção de responsabilidade do AVR em algum lugar para você não usar os MCUs normalmente usados ​​por Arduino em sistemas de suporte à vida).

Ricardo
fonte
1
Ótimo! A melhor resposta que eu já vi no Arduino.SE!
O cara com o chapéu
1
Obrigado!! Acho que devemos nos esforçar para dar ótimas respostas, tanto quanto possível. Mas me preocupa um pouco o fato de não termos tantos ESPECIALISTAS EM EE REAIS que poderiam procurar respostas como a minha e encontrar algum erro flagrante. Na verdade, essa foi a razão pela qual eu postei a resposta, embora eu não saiba muito sobre os MCUs AVR. Isso é para ver se conseguimos alguém para corrigi-lo. Certamente, não queremos que pensadores inteligentes como eu digam coisas que não estão certas e se safem. Mas isso provavelmente é uma discussão para o site Meta.
Ricardo
5
@ Ricardo - Um comentário que eu faria é que variáveis ​​inicializadas não explicitamente não são necessariamente não inicializadas. As variáveis ​​definidas fora das funções geralmente têm o que é chamado de "duração automática de armazenamento", que depois é inicializada como zero. Consulte en.cppreference.com/w/cpp/language/default_initialization para obter mais informações. O comportamento de inicialização é complexo o suficiente para ser provavelmente perigoso, mas fazer declarações gerais provavelmente não é uma ótima idéia.
Connor Lobo
1
Além disso, a SRAM é inicializada como 0 na redefinição ou inicialização, para que você possa fazer algumas suposições informadas sobre variáveis ​​não inicializadas, se desejar viver perigosamente. Você não deve confiar nesse comportamento, mas é interessante.
Connor Lobo
1
Há um exemplo interessante do que acontece quando você fica sem SRAM aqui: electronics.stackexchange.com/questions/42049/… . Basicamente, a pilha derruba parte da pilha, ou vice-versa. Isso pode fazer coisas interessantes, como corromper uma parte do quadro da pilha (quebra de função, etc.) ou gravar dados inválidos em variáveis.
Connor Lobo
9

Não há exceções de tempo de execução. Há apenas comportamento indefinido.

Realmente, não há exceções em tudo . Se você tentar executar uma operação inválida, seus resultados serão desconhecidos.

Não há verificação de tempo de execução, exceto o que você implementa. Seu programa está sendo executado em hardware bare-metal. É o equivalente à área de trabalho da execução no anel 0 o tempo todo, porque o ATmega não possui anéis .

Connor Wolf
fonte
6

Há um mecanismo que pode obter o MCU de um estado irregular e é o cronômetro do watchdog . Se você estiver implementando algum código que será executado repetidamente em um loop, que não será executado por mais tempo do que um tempo fixo, você pode definir esse período como período de observação e ativar o timer.

Então, você deve reiniciar repetidamente o timer no loop. Se o seu código congelar em algum loop de condição que nunca terminará, o cão de guarda contará como zero e, eventualmente, redefinirá o MCU.

Dessa forma, você está perdendo dados, mas se você executar o AVR WDT no modo de interrupção, poderá armazenar alguns dados antes de redefinir o MCU.

Portanto, o timer do watchdog pode proteger seu código de loops intermináveis ​​não desejados ocasionais.

Documentation: AVR132: Usando o timer de watchdog aprimorado

nio
fonte
5

Você precisaria de um depurador de hardware para algo assim. Mas geralmente você verá que o programa não está se comportando conforme o esperado e precisará examinar essa seção do código para identificar o problema.

Uma maneira comum / rápida / fácil de fazer isso é adicionar instruções de impressão para imprimir os valores das variáveis ​​ou qualquer outra coisa, para que você saiba que o programa chega a esse ponto no código sem problemas. Isso ajudará você a isolar ainda mais o problema.

Acredito que o VisualMicro tenha alguma funcionalidade de depuração incorporada.

sachleen
fonte
3

Eu diria que a CPU do AVR não possui nenhuma ferramenta de detecção ou recuperação de erros. Pode simplesmente parar ou continuar ignorando o erro e as consequências. Como disse sachleen, você deve adicionar algumas instruções de depuração em seu programa que imprimem dados no meio de uma operação, para testar se está funcionando. Se você usar um emulador ou definir pontos de interrupção, poderá encontrar facilmente um problema.

O médico
fonte
-2

O Arduino será reiniciado (ou seja, será reiniciado setup()e loop()).

user28739
fonte
1
Não necessariamente. Um erro em tempo de execução pode fazer o programa entrar em loop sem reiniciar.
Nick Gammon