วิธีการค้นหาข้อผิดพลาดหน่วยความจำล้นในรหัส Arduino C?


10

หลายครั้งที่ฉันมีผลลัพธ์ที่น่าสงสัยใน Serial Monitor หลังจากอัปโหลดรหัสไปยัง Arduino: เช่นเอาท์พุทนิรันดร์ของช่องว่างหรือตัดสายหรือสัญญาณรบกวน

เนื่องจากไม่มีข้อผิดพลาดในการคอมไพล์หรือคำเตือนใน Arduino IDE ฉันคิดว่า Arduino เสียหาย แต่หลังจากการทดสอบบางอย่างฉันพบว่ามีข้อผิดพลาดไม่ทุกชนิดที่ถูกรวบรวมโดยคอมไพเลอร์ Arduino IDE - โดยเฉพาะอย่างยิ่งเมื่อกำหนดตัวแปรในวงสำหรับโครงสร้างอาร์เรย์ ดูเหมือนว่าจะทำให้ Arduino ล้มเหลวในระยะเวลาอันสั้น

ฉันจะค้นพบข้อผิดพลาดที่ไม่ได้แสดงโดย Arduino IDE ได้อย่างไร

คำตอบ:


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

สาเหตุที่พบบ่อยที่สุดสำหรับการใช้ RAM หมดไปคือการใช้วัตถุ String หรือใช้อาร์เรย์อักขระคงที่จำนวนมาก (สตริงรูปแบบ c)

Forutantly IDE 1.0.4 รวมถึงการแก้ไขเพื่อ malloc ซึ่งได้รบกวนสตริงวัตถุเป็นเวลานานมาก

เพื่อลด RAM ที่สูญเสียไปโดยสายอักขระคงที่เช่น:

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
นี่เป็นคำถามเก่า แต่ใช่มี debuggers ที่เหมาะสมสำหรับatmel ATmega MCUs ไม่มี debuggers สำหรับarduinosเนื่องจาก arduino toolchain และ "IDE" นั้นเป็นของเล่น
Connor Wolf

1
ความจริงแล้วคำใบ้ของคุณด้วย F () ช่วยเราประหยัดได้ถึงร้อยไบต์ใน RAM!
powtac

1
ฉันได้รับรวบรวมข้อผิดพลาดเมื่อใช้ F () //กับสตริงที่มี :-(
powtac

ฉันได้รับข้อผิดพลาดในการคอมไพล์ใน Arduino 1.5.7 ...
powtac

3

ดูเหมือนว่าคุณกำลังพูดถึงข้อผิดพลาดรันไทม์ (ของหน่วยความจำรั่ว / ประเภท segfault) ที่นี่

ไม่มีวิธีใดที่จะค้นพบข้อผิดพลาดดังกล่าว (เว้นแต่ว่าคุณใช้รหัสผ่านอย่างระมัดระวัง) ในรหัสที่เขียนไปแล้ว อย่างไรก็ตามมันค่อนข้างง่ายที่จะป้องกันไม่ให้สิ่งเหล่านี้เกิดขึ้นในขณะที่เขียนโค้ด แค่ระวังให้มากเมื่อเขียนลูปหรือเรียกซ้ำ ถามตัวเองว่า "นี่จะออกไปจากมือได้ไหม" หากดูเหมือนว่าสิ่งเหล่านี้เป็นขอบเขตสำหรับ "หลุดมือไป" ให้เขียนโค้ดเพื่อป้องกันสิ่งนั้น

เกี่ยวกับ segfaults - เพียงแค่ตรวจสอบค่าขอบเขตของดัชนีอาร์เรย์และคุณควรจะตกลง หากคุณกำลังใช้พอยน์เตอร์อยู่โปรดระมัดระวังด้วยตัวชี้เลขคณิต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.