Як виявити помилки переповнення пам'яті в коді Arduino C?


10

Після завантаження коду в Arduino я кілька підозрілих виходів на Serial Monitor: на зразок вічного виводу пробілів або раптово вирізаних рядків або скремблированих рядків.

Оскільки в ID ID Arduino не було помилки компіляції чи попередження, я вважав, що Arduino був зламаний, але після деяких тестів я виявив, що компілятор Arduino IDE не вловлює всі види помилок - особливо при призначенні змінних у циклі для структур масиву. Це, здається, руйнує Ардуїно за короткий проміжок часу.

Як я можу виявити помилки, які не відображаються IDE Arduino?

Відповіді:


10

Бібліотека MemoryFree може допомогти вам знайти ризики з використанням пам'яті.

Приклад:

#include <MemoryFree.h>

// On Arduino Duemilanove with ATmega328:
//
// Reported free memory with str commented out:
// 1824 bytes
//
// Reported free memory with str and Serial.println(str) uncommented:
// 1810
//
// Difference: 14 bytes (13 ascii chars + null terminator)

// 14-bytes string
//char str[] = "Hello, world!";


void setup() {
    Serial.begin(115200);
}


void loop() {
    //Serial.println(str);

    Serial.print("freeMemory()=");
    Serial.println(freeMemory());

    delay(1000);
}

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


7

Найбільш поширеною причиною вичерпання оперативної пам'яті є використання об'єкта String або використання безлічі масивів постійного символу (c-style string).

Назавжди IDE 1.0.4 включає виправлення на malloc, яке страждає на String-об'єкт дуже довгий час.

Для зменшення оперативної пам'яті витрачається на рядки з постійними символами, такі як:

Serial.print("Hello World");  // This consumes RAM!

Можна використовувати макрос F (). Цей макрос змусить масив символів залишитися в PROGMEM. При використанні масиву витрачається лише один байт пам'яті.

Serial.print(F("Hello World"));  // Keeps the character-array in PROGMEM

Майте на увазі, що рядки, збережені в PROGMEM, не можуть бути змінені під час виконання.

Що стосується відкриття, без налагоджувача чи контролера пам’яті вам доведеться використовувати старомодні детективні методи, щоб знайти, де виникають проблеми.


1
Дякую за корисну відповідь! Насправді немає налагоджувача пам'яті підтримки IDE?
powtac

1
Це давнє питання, але так, є належні налагоджувачі для Atmel ATmega MCU. Немає налагоджувачів для ардуїно , оскільки ланцюжок інструментів arduino та "IDE" - це в основному іграшка.
Коннор Вольф

1
Насправді ваш натяк на F () врятував нам кілька сотень байт в оперативній пам’яті!
powtac

1
Я отримую помилку компіляції при використанні F () з рядками, які містять //. :-(
powtac

Я отримую цю помилку компіляції на Arduino 1.5.7 ...
powtac

3

Схоже, ви тут говорите про помилки під час виконання (типу витоку пам'яті / segfault).

Не існує жодного способу виявити подібні помилки (якщо ви не дуже обережно розчісуєте код) у коді, який уже написаний. Однак, досить просто запобігти цьому під час написання коду. Будьте дуже обережні при написанні циклів або рекурсивних дзвінків; запитайте себе: "це може вийти з рук?". Якщо схоже, що це поле для того, щоб "вийти з рук", тоді напишіть код для захисту від цього.

Про segfaults - просто перевірте граничні значення індексів масиву, і вам повинно бути гаразд. Якщо ви використовуєте вказівники, будьте обережні з арифметикою вказівника.

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