« Arduino TexitStringライブラリのメモリーリーク | トップページ | ArduinoライブラリのMCUタイプ依存性 »

Arduinoメールチェッカー(その3)

メールチェッカーの不安定要因であたメモリーリーク問題が解決したため、最新版のコードをアップします。

 「MailChecker_pub20090609.zip」をダウンロード

対策は、Arduino TexitStringライブラリのメモリーリークに示したTextStringライブラリコードの変更になります。変更箇所のみを以下に再掲します。

Stringライブラリのコードに、以下のデストラクタを追加します。

<WString.hへの追加>
  public:
    ~String();   ←追加

<WString.cppへの追加>
 String::~String()
 {
   free(_array);
 }

あわせて、メールチェッカーのコードも若干見直しを行いました。

  • メールサーバーに送信するpop3コマンド文字列を保持するバッファ量を拡大
  • String.indexOf()メンバー関数の引数(検索する文字の指定)を、" "から' 'に変更。
    " "を指定するとStringオブジェクトを引数として渡します。
    ' 'の場合は、charのスペース(0x20)を引数として渡します。
    → " "を引数にした場合のメモリーリークは解決したのですが、処理が重いオブジェクトを使用するまでもないため、charデータ型に変更しました

メールチェッカーのメモリー使用量

メールチェッカーのコードがスタック・ヒープをどの程度使っているのかを調べてみました。yagihiroさんのblogを参考にしました。

IDEと一緒にインストールされる「avr-objdump, avr-nm」を使用してヒープの割当を調べると以下の通りでした。elfファイルは、スケッチを保存したフォルダーのapplet配下に生成されます。

C:>avr-objdump -h MailChecker23.elf

MailChecker23.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         000001f8  00800100  00003c26  00003cba  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00003c26  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          0000026b  008002f8  008002f8  00003eb2  2**0
                  ALLOC

.data + .bssセクションが 0x463 = 1123byte確保されています。この領域は、グローバルないしは静的に宣言している変数・インスタンス・定数などを格納しているようです。私は、SRAM 2KBのATmega328を使用しているため、SRAMの約半分をこの領域で使用していることになりす。

avr-nmコマンドにて、シンボル毎のメモリ割付を確認することができます。
C:>avr-nm -n -C MailChecker23.elf

00800100 D __data_start
008002f8 B __bss_start
 ~中略~
008002f8 D __data_end
008002f8 D _edata
 ~中略~
00800563 B __bss_end
00800563 N __heap_start

ヒープが0x0563から始まることが分かります。

Arduino TexitStringライブラリのメモリーリークに示した、heap pointerを出力するコードを入れて、pop3サーバーアクセス開始時のheap pointerを調べると以下でした。

Heap ptr :6C3
Stack ptr:8D6

プログラム開始時に確保するヒープ領域が0x160 = 352byte程度あることを示します。

Stack Endが0x08FF(2KBのSRAM空間の終わり)だとすると、Stack pointerが0x8D6のため、スタックを0x29 = 41byte使っていることになります。

Stack pointer - Heap pointerが空きメモリーということになるため、0x213 = 531byteが空きメモリーということになります。DateTime, NTPなどのライブラリも取り込んだため、残りメモリーが少なくなってきました。

上記から分かったメモリーマップのイメージを図にすると以下となります。Memmap_3

グローバル変数を多用して汚いコードになっている部分を、関数への引数渡しに書き替えてデーターの流れをすっきり見るようにしようかとも思ったのですが、スタックの使用量増加がよく分からないため(その分.data + .bssは減るのですが)当面は現状のままで行こうと思います。

|

« Arduino TexitStringライブラリのメモリーリーク | トップページ | ArduinoライブラリのMCUタイプ依存性 »

Arduino」カテゴリの記事

コメント

ああ、なるほど、Arduinoと言うかAvr-Gccのメモリ割付状況はこうやって調べるのですか。早速ネタに使わせてもらおう。

メモリ割付状況なんて、「気にする人は気にする。気にならない人は全く無視するか、そんな物がある事すら知らない。」と言うのが今のArduinoだと思うんですけれど、ならappletなんて中間ファイルを吐き出すフォルダーは気にする人位しか見ないのだから標準でMAP出力してくれれば良いのに!と思ってしまう。

cores以下にあるmakefileをいじれば良いのかな。

投稿: hamayan | 2009年6月10日 (水) 10時05分

どうぞネタにしてやって下さい。私が発見したテクではありませんが、、

coreにあるmakefineを眺めてみたのですが、冒頭のコメントに、「This makefile allows you to build sketches from the command line without the Arduino environment (or Java).」なんてことが書いてあります。CLI make用ですか!

以下の定義があるためSymbol table/mapを生成するのではと期待したのですが、エラーが発生してうまくmakeできませんでした(Windows環境ではダメで、Linux環境ならうまくいくのかしら)。
--- makefileの抜粋 ----
OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump
NM = $(AVR_TOOLS_PATH)/avr-nm

# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@

# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@

投稿: todotani | 2009年6月10日 (水) 22時37分

コメントを書く



(ウェブ上には掲載しません)




« Arduino TexitStringライブラリのメモリーリーク | トップページ | ArduinoライブラリのMCUタイプ依存性 »