Làm thế nào để phát hiện ra lỗi tràn bộ nhớ trong mã Arduino C?


10

Đã nhiều lần tôi có một số đầu ra đáng ngờ trên Màn hình nối tiếp sau khi tải mã lên Arduino: như đầu ra vĩnh cửu của khoảng trắng hoặc đột ngột cắt chuỗi hoặc chuỗi bị xáo trộn.

Do không có lỗi biên dịch hoặc cảnh báo trong Arduino IDE, tôi nghĩ rằng Arduino đã bị hỏng nhưng sau một số thử nghiệm tôi phát hiện ra rằng không phải tất cả các loại lỗi đều bị trình biên dịch Arduino IDE bắt gặp - đặc biệt là khi gán biến trong vòng lặp cho cấu trúc mảng. Điều này dường như đánh sập Arduino trong một khoảng thời gian ngắn.

Làm thế nào tôi có thể phát hiện ra các lỗi không được hiển thị bởi Arduino IDE?

Câu trả lời:


10

Các thư viện MemoryFree thể giúp bạn tìm rủi ro với việc sử dụng bộ nhớ.

Thí dụ:

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

Tôi không chắc chắn nếu tài khoản MemoryFree cho con trỏ ngăn xếp. Nếu con trỏ ngăn xếp của bạn va chạm với con trỏ heap của bạn, bạn có thể gặp lỗi phân đoạn.


7

Nguyên nhân phổ biến nhất gây cạn kiệt RAM là sử dụng đối tượng String hoặc sử dụng nhiều mảng ký tự không đổi (chuỗi kiểu c).

Forutantly IDE 1.0.4 bao gồm một bản sửa lỗi cho malloc đã làm hỏng đối tượng String trong một thời gian rất dài.

Để giảm RAM lãng phí bởi các chuỗi ký tự không đổi như:

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

Bạn có thể sử dụng macro F (). Macro này sẽ buộc mảng ký tự ở lại trong PROGMEM. Khi mảng được sử dụng, chỉ một byte bộ nhớ được tiêu thụ.

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

Hãy nhớ rằng các chuỗi được lưu trữ trong PROGMEM không thể bị thay đổi trong thời gian chạy.

Theo như khám phá, không có trình gỡ lỗi hoặc bộ điều khiển bộ nhớ, bạn phải sử dụng các kỹ thuật thám tử lỗi thời để tìm ra nơi xảy ra sự cố.


1
Cảm ơn bạn đã trả lời hữu ích! Có thực sự không có IDE hỗ trợ trình gỡ lỗi bộ nhớ?
powtac

1
Đây là một câu hỏi cũ, nhưng vâng, có những trình sửa lỗi thích hợp cho MCU của Atmel ATmega . Không có trình gỡ lỗi cho arduinos , vì chuỗi công cụ arduino và "IDE" về cơ bản là một món đồ chơi.
Sói Connor

1
Trên thực tế, gợi ý của bạn với F () đã tiết kiệm cho chúng tôi hàng trăm byte RAM!
powtac

1
Tôi gặp lỗi biên dịch khi sử dụng F () với các chuỗi có chứa //. :-(
powtac

Tôi nhận được lỗi biên dịch này trên Arduino 1.5.7 ...
powtac

3

Có vẻ như bạn đang nói về lỗi thời gian chạy (của loại rò rỉ bộ nhớ / segfault) ở đây.

Không có cách nào để phát hiện ra các lỗi như vậy (trừ khi bạn chải rất kỹ thông qua mã) trong mã đã được viết. Tuy nhiên, khá dễ dàng để ngăn chặn những điều này xảy ra trong khi viết mã. Chỉ cần rất cẩn thận khi viết các vòng lặp hoặc các cuộc gọi đệ quy; Hãy tự hỏi mình "điều này có thể ra khỏi tầm tay?". Nếu có vẻ như đây là phạm vi để nó "ra tay", thì hãy viết mã để bảo vệ chống lại điều đó.

Về segfaults - chỉ cần kiểm tra các giá trị biên của các chỉ số mảng và bạn phải ổn. Nếu bạn đang sử dụng con trỏ, thì hãy cẩn thận với số học con trỏ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.