Що станеться, якщо є помилка виконання?


17

Що станеться, якщо в програмі є помилка виконання? Чи просто зупиниться виконання програми? Чи є якийсь спосіб змусити мене змусити Ардуїно сказати, в чому помилка?

Відповіді:


21

Спочатку давайте подивимось кілька прикладів того, що може піти не так.

Неініціалізовані локальні змінні

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

Як вказував Едгар Боне в коментарях, локальні змінні, як statusу наведеному вище коді, неявно не ініціалізуються компілятором C ++. Отже, результат наведеного вище коду невизначений. Щоб уникнути цього, переконайтеся, що ви завжди присвоюєте значення своїм локальним змінним.

Речі дещо відрізняються із глобальними та статичними змінними:

Глобальні та статичні змінні гарантуються ініціалізацією до 0 стандартом C.

Джерело: Довідник посібника AVR Libc - Часті запитання - Чи не слід ініціалізувати всі мої змінні?

Це означає, що ви не повинні турбуватися про ініціалізацію їх до 0 у своєму коді. Насправді вам слід справді уникати цього, оскільки ініціалізація може втратити пам'ять. Ініціалізуйте їх лише до значень, відмінних від 0.

Переповнення пам'яті

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

Перша проблема тут полягає в тому, що ви не знаєте, що буде призначено v, але ще гірше те, що ви не знаєте, що ви зіпсували з присвоєнням позиції -100 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
}

Перший дзвінок до funcPtr()насправді буде закликом до doSomething(). Дзвінки, як і другий, можуть призвести до невизначеної поведінки.

Інші погані речі, які можуть статися

Ну, наприклад, ви можете закінчити оперативну пам'ять. Що ще. У будь-якому випадку, я думаю, що ваша програма буде продовжувати працювати, ймовірно, не так, як ви її планували.

Види захисту

У комп'ютерних системах подібні проблеми зазвичай вирішуються на різних рівнях:

  1. За укладачем
  2. За мовою виконання програми (як, наприклад, у Java).
  3. Операційною системою або процесором (якщо ваша пам'ять має доступ до позиції поза межами адресного простору, відведеного для вашої програми, ОС або процесор можуть мати механізми безпеки для запобігання цьому)

Arduinos має обмежений захист компілятора, і, мабуть, нічого іншого. Хороша новина полягає в тому, що вони не мають багатозадачних завдань, тому єдина програма, на яку впливає, - це ваша. У будь-якому випадку, будь-який з цих помилок призведе до помилкової поведінки.

Відповіді

Припущення - всі проблеми, про які я говорив вище, - це проблеми виконання.

Що станеться, якщо в програмі є помилка виконання?

Програма триватиме, і те, що станеться, залежатиме від побічних ефектів помилки виконання. Виклик покажчика нульової функції, ймовірно, змусить програму перейти до невідомого місця.

Чи просто зупиниться виконання програми?

Ні, це триватиме так, ніби нічого надзвичайного не сталося, ймовірно, робити те, чого ви цього не мали намір робити. Він може скидатися або діяти помилково. Це може перетворити деякі входи у виходи та записати датчик або два (але це малоймовірно ).

Чи є якийсь спосіб змусити Ардуїно сказати мені, в чому помилка?

Я не думаю, що так. Як я вже говорив раніше, механізмів захисту немає. Немає підтримки мови, немає ОС, немає апаратних перевірок на доступ до пам'яті поза межами (завантажувач також не вважається). Ви просто повинні бути обережними зі своєю програмою і, ймовірно, встановлювати власні захисні мережі.

Причина відсутності захисту, ймовірно, в тому, що контролери Arduino занадто дешеві, мають занадто мало пам’яті і не повинні запускати щось занадто важливе (так, AVR десь здається, що AVR десь відмовиться від вас, щоб не використовувати MCU, які зазвичай використовуються Ардуїно в системах життєзабезпечення).


1
Чудово! Найкраща відповідь, яку я бачив на Arduino.SE поки що!
Хлопець із Шапочкою

1
Спасибі!! Я думаю, що ми повинні прагнути якомога більше давати чудові відповіді. Але мене трохи непокоїть той факт, що у нас немає стільки РЕАЛЬНИХ ДОСВІДІВ, які могли б дивитись на відповіді, як мої, і знаходити будь-які яскраві помилки. Насправді саме тому я опублікував відповідь, хоча я не знаю так багато про AVR MCU. Отож, щоб побачити, чи змусимо когось це виправити. Ми впевнені, що не хочемо розумних пентентів, як я, які говорять речі, які не є правильними, і відводяться від цього. Але це, мабуть, дискусія для сайту Meta.
Рікардо

5
@Ricardo - Один із коментарів, який я б хотів зробити, - це те, що не явно ініціалізовані змінні не обов'язково є неініціалізованими. Змінні, визначені поза функціями, зазвичай мають назву "тривалість автоматичного зберігання", які потім ініціалізуються за замовчуванням до нуля. Для отримання додаткової інформації див. En.cppreference.com/w/cpp/language/default_initialization . Поведінка ініціалізації є досить складною, що на неї, мабуть, небезпечно покластися, але робити викладені бланки, мабуть, не є чудовою ідеєю.
Вонор Коннор

1
Крім того, SRAM ініціалізується до 0 при скиданні або запуску, так що ви можете зробити деякі поінформовані здогадки про неініціалізовані змінні, якщо ви хочете жити небезпечно. Не варто покладатися на таку поведінку, але це цікаво.
Вонор Коннор

1
Існує цікавий приклад того , що відбувається , коли ви біжите з SRAM тут: electronics.stackexchange.com/questions/42049 / ... . В основному, стек клобує частину купи, або навпаки. Це може робити цікаві речі, такі як пошкодження деякої частини кадру стека (порушення функції повернення тощо) або записування недійсних даних у змінні.
Вонор Коннор

9

Винятків із виконання не існує. Є лише невизначена поведінка.

Дійсно, винятків взагалі немає . Якщо ви спробуєте виконати недійсну операцію, результати будуть невідомі.

Перевірки часу виконання взагалі немає, крім того, що ви реалізуєте. Ваша програма працює на металоконструкціях з голого металу. Це настільний еквівалент роботи в ring-0 весь час, тому що в ATmega немає кілець .


6

Є один механізм, який може отримати MCU з нестабільного стану, і це таймер сторожового часу . Якщо ви реалізуєте якийсь код, який буде неодноразово виконуватись у циклі, який не запускатиметься більше, ніж певний фіксований час, ви можете встановити цей час як термін вахти та включити таймер.

Потім вам доведеться неодноразово скидати таймер у циклі. Якщо ваш код замерзає в певному циклі стану, який ніколи не закінчиться, сторожовий дог зараховується до нуля і врешті-решт скидає MCU.

Таким чином ви втрачаєте дані, але якщо запустити AVR WDT в режимі переривання, ви можете зберігати деякі дані перед скиданням MCU.

Тож сторожовий таймер може захистити ваш код від випадкових непередбачуваних нескінченних циклів.

Документація: AVR132: Використання вдосконаленого таймеру сторожової собаки


5

Вам знадобиться апаратний відладчик для подібного. Але зазвичай ви побачите, що програма не веде себе так, як ви її очікували, і вам доведеться переглянути цей розділ коду, щоб визначити проблему.

Поширений / швидкий / простий спосіб зробити це - додати оператори друку для друку значень змінних або просто нічого, щоб ви знали, що програма потрапляє до цієї точки коду без проблем. Це допоможе вам ще більше відокремити проблему.

Я вважаю , що VisualMicro має деякі функціональні можливості налагодження вбудовані в.


3

Я припускаю, що у процесора AVR немає інструментів виявлення або відновлення помилок. Він може просто зупинитися або продовжувати ігнорувати помилку та наслідки. Як сказав sachleen, вам слід додати деякі програми налагодження у вашу програму, які роздруковують дані в середині операції, щоб перевірити, чи працює вона. Якщо ви використовуєте емулятор і встановлюєте точки перерви, ви можете легко знайти проблему.


-2

Arduino перезавантажиться (тобто відновиться setup()і loop()).


1
Не обов'язково. Помилка під час виконання програми може змусити програму перейти у цикл без перезавантаження.
Нік Гаммон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.