Bagaimana cara menemukan kesalahan limpahan memori dalam kode Arduino C?

10

Beberapa kali saya memiliki beberapa keluaran mencurigakan pada Serial Monitor setelah mengunggah kode ke Arduino: seperti output abadi spasi putih atau tiba-tiba memotong string atau string acak.

Karena tidak ada kesalahan kompilasi atau peringatan di Arduino IDE saya pikir Arduino rusak tetapi setelah beberapa tes saya menemukan bahwa tidak semua jenis kesalahan ditangkap oleh kompiler Arduino IDE - terutama ketika menugaskan variabel dalam loop untuk struktur array. Ini tampaknya menabrak Arduino dalam waktu singkat.

Bagaimana saya menemukan kesalahan yang tidak ditampilkan oleh Arduino IDE?

powtac
sumber

Jawaban:

10

The perpustakaan MemoryFree dapat membantu Anda menemukan risiko dengan penggunaan memori.

Contoh:

#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);
}

Saya tidak yakin apakah MemoryFree menyumbang penunjuk tumpukan. Jika stack pointer Anda bertabrakan dengan heap pointer Anda, Anda dapat mengalami kesalahan segmentasi.


sumber
7

Penyebab paling umum untuk kehabisan RAM adalah menggunakan objek String atau menggunakan banyak array karakter konstan (c-style string).

Forutantly IDE 1.0.4 mencakup perbaikan untuk malloc yang telah mengganggu objek-String untuk waktu yang sangat lama.

Untuk mengurangi RAM yang terbuang oleh string karakter konstan seperti:

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

Anda dapat menggunakan makro F (). Makro ini akan memaksa array karakter untuk tetap di PROGMEM. Ketika array digunakan, hanya satu byte memori yang dikonsumsi.

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

Ingatlah bahwa string yang disimpan dalam PROGMEM tidak dapat diubah selama runtime.

Sejauh penemuan berjalan, tanpa debugger atau pengontrol memori, Anda harus menggunakan teknik detektif kuno untuk menemukan di mana masalah terjadi.

baldengineer
sumber
1
Terima kasih atas jawaban yang bermanfaat! Sebenarnya tidak ada dukungan memori debugger IDE?
powtac
1
Ini adalah pertanyaan lama, tapi ya, ada debugger yang tepat untuk atmel ATmega MCU. Tidak ada debugger untuk arduinos , karena arduino toolchain dan "IDE" pada dasarnya adalah mainan.
Connor Wolf
1
Sebenarnya petunjuk Anda dengan F () menyelamatkan kami beberapa ratus byte dalam RAM!
powtac
1
Saya mendapatkan kesalahan kompilasi saat menggunakan F () dengan string yang berisi //. :-(
powtac
Saya mendapatkan kesalahan kompilasi ini di Arduino 1.5.7 ...
powtac
3

Sepertinya Anda berbicara tentang kesalahan runtime (dari tipe kebocoran memori / segfault) di sini.

Tidak ada cara untuk menemukan kesalahan seperti itu (kecuali Anda menyisir kode dengan sangat hati-hati) dalam kode yang sudah ditulis. Namun, cukup mudah untuk mencegah hal ini terjadi saat menulis kode. Berhati-hatilah saat menulis loop atau panggilan rekursif; tanyakan pada diri sendiri "bisakah ini lepas kendali?". Jika sepertinya ini adalah ruang untuk "keluar dari tangan", maka tulis kode untuk melindunginya.

Tentang segfaults - cukup periksa nilai batas indeks array dan Anda harus OK. Jika Anda menggunakan pointer, maka harap berhati-hati dengan aritmatika pointer.

Manishearth
sumber