Що станеться, якщо в програмі є помилка виконання? Чи просто зупиниться виконання програми? Чи є якийсь спосіб змусити мене змусити Ардуїно сказати, в чому помилка?
Що станеться, якщо в програмі є помилка виконання? Чи просто зупиниться виконання програми? Чи є якийсь спосіб змусити мене змусити Ардуїно сказати, в чому помилка?
Відповіді:
Спочатку давайте подивимось кілька прикладів того, що може піти не так.
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()
. Дзвінки, як і другий, можуть призвести до невизначеної поведінки.
Ну, наприклад, ви можете закінчити оперативну пам'ять. Що ще. У будь-якому випадку, я думаю, що ваша програма буде продовжувати працювати, ймовірно, не так, як ви її планували.
У комп'ютерних системах подібні проблеми зазвичай вирішуються на різних рівнях:
Arduinos має обмежений захист компілятора, і, мабуть, нічого іншого. Хороша новина полягає в тому, що вони не мають багатозадачних завдань, тому єдина програма, на яку впливає, - це ваша. У будь-якому випадку, будь-який з цих помилок призведе до помилкової поведінки.
Припущення - всі проблеми, про які я говорив вище, - це проблеми виконання.
Що станеться, якщо в програмі є помилка виконання?
Програма триватиме, і те, що станеться, залежатиме від побічних ефектів помилки виконання. Виклик покажчика нульової функції, ймовірно, змусить програму перейти до невідомого місця.
Чи просто зупиниться виконання програми?
Ні, це триватиме так, ніби нічого надзвичайного не сталося, ймовірно, робити те, чого ви цього не мали намір робити. Він може скидатися або діяти помилково. Це може перетворити деякі входи у виходи та записати датчик або два (але це малоймовірно ).
Чи є якийсь спосіб змусити Ардуїно сказати мені, в чому помилка?
Я не думаю, що так. Як я вже говорив раніше, механізмів захисту немає. Немає підтримки мови, немає ОС, немає апаратних перевірок на доступ до пам'яті поза межами (завантажувач також не вважається). Ви просто повинні бути обережними зі своєю програмою і, ймовірно, встановлювати власні захисні мережі.
Причина відсутності захисту, ймовірно, в тому, що контролери Arduino занадто дешеві, мають занадто мало пам’яті і не повинні запускати щось занадто важливе (так, AVR десь здається, що AVR десь відмовиться від вас, щоб не використовувати MCU, які зазвичай використовуються Ардуїно в системах життєзабезпечення).
Винятків із виконання не існує. Є лише невизначена поведінка.
Дійсно, винятків взагалі немає . Якщо ви спробуєте виконати недійсну операцію, результати будуть невідомі.
Перевірки часу виконання взагалі немає, крім того, що ви реалізуєте. Ваша програма працює на металоконструкціях з голого металу. Це настільний еквівалент роботи в ring-0 весь час, тому що в ATmega немає кілець .
Є один механізм, який може отримати MCU з нестабільного стану, і це таймер сторожового часу . Якщо ви реалізуєте якийсь код, який буде неодноразово виконуватись у циклі, який не запускатиметься більше, ніж певний фіксований час, ви можете встановити цей час як термін вахти та включити таймер.
Потім вам доведеться неодноразово скидати таймер у циклі. Якщо ваш код замерзає в певному циклі стану, який ніколи не закінчиться, сторожовий дог зараховується до нуля і врешті-решт скидає MCU.
Таким чином ви втрачаєте дані, але якщо запустити AVR WDT в режимі переривання, ви можете зберігати деякі дані перед скиданням MCU.
Тож сторожовий таймер може захистити ваш код від випадкових непередбачуваних нескінченних циклів.
Документація: AVR132: Використання вдосконаленого таймеру сторожової собаки
Вам знадобиться апаратний відладчик для подібного. Але зазвичай ви побачите, що програма не веде себе так, як ви її очікували, і вам доведеться переглянути цей розділ коду, щоб визначити проблему.
Поширений / швидкий / простий спосіб зробити це - додати оператори друку для друку значень змінних або просто нічого, щоб ви знали, що програма потрапляє до цієї точки коду без проблем. Це допоможе вам ще більше відокремити проблему.
Я вважаю , що VisualMicro має деякі функціональні можливості налагодження вбудовані в.
Я припускаю, що у процесора AVR немає інструментів виявлення або відновлення помилок. Він може просто зупинитися або продовжувати ігнорувати помилку та наслідки. Як сказав sachleen, вам слід додати деякі програми налагодження у вашу програму, які роздруковують дані в середині операції, щоб перевірити, чи працює вона. Якщо ви використовуєте емулятор і встановлюєте точки перерви, ви можете легко знайти проблему.
Arduino перезавантажиться (тобто відновиться setup()
і loop()
).