Arduino Cコードでメモリオーバーフローエラーを発見するにはどうすればよいですか?


10

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スタイルの文字列)を使用することです。

幸いにもIDE 1.0.4には、非常に長い間Stringオブジェクトを悩ませてきたmallocの修正が含まれています。

次のような定数文字列によって浪費されるRAMを減らすには:

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

F()マクロを使用できます。このマクロは、文字配列をPROGMEMにとどまらせます。配列を使用すると、1バイトのメモリのみが消費されます。

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

PROGMEMに格納されている文字列は、実行時に変更できないことに注意してください。

ディスカバリーに関する限り、デバッガーやメモリーコントローラーがない場合は、昔ながらの検出手法を使用して、問題が発生している場所を見つける必要があります。


1
役立つ回答をありがとう!IDEサポートメモリデバッガーは本当にありませんか?
powtac 2013

1
これは古い質問ですが、はい、atmel ATmega MCU には適切なデバッガがあります。以下のためのデバッガはありませんarduinosは arduinoのツールチェーンおよび「IDE」は基本的には玩具ですので、。
コナーウルフ

1
実際、F()を使用したヒントにより、RAMが数百バイト節約されました。
powtac 2014

1
を含む文字列でF()を使用すると、コンパイルエラーが発生します//。:-(
powtac

Arduino 1.5.7でこのコンパイルエラーが発生します...
powtac

3

ここで(メモリリーク/ segfaultタイプの)ランタイムエラーについて話しているように見えます。

すでに記述されているコードでこのようなエラーを発見する方法はありません(コードを非常に注意深く調べない限り)。しかし、一方で起こってからこれらを防ぐために非常に簡単です書いたコードを。ループや再帰呼び出しを作成するときは十分注意してください。「これは手に負えませんか?」と自問してください。これらが「手に負えなくなる」余地があると思われる場合は、それを防ぐためのコードを記述します。

segfaultsについて-配列のインデックスの境界値を確認するだけで問題ありません。ポインタを使用している場合は、ポインタ演算に注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.