1

動的リストにデータを保存したいarduinoプログラムがあります。このために私は以下を使用しますstruct

struct Project {
  boolean         status;
  String          name;
  struct Project* nextProject;
};

Projectここで、外部データに応じて、動的な量のオブジェクトを生成します。私は最初のProjectオブジェクトのみを変数として持っており、残りはnextProjectポインターを介して取得できます。

Projectオブジェクトの生成は、loop毎分私の中で行われます。問題は、時々、それが空になるまで記憶を失うことです。
これは私のメインループがどのように見えるかです:

void loop() {
  webServer(server);
  webClient();

  if (parseTimer(60)) {
    sendRequest();
  }
}

(60秒ごとparseTimerに戻るノンブロッキング遅延関数です。オブジェクトを生成します)truesendRequestProject

メモリを測定する私の方法:

uint8_t* stackptr;
uint8_t* heapptr;

long getFreeMemory() {
  stackptr = (uint8_t *) malloc(4);
  heapptr  = stackptr;
  free(stackptr);
  stackptr = (uint8_t *) (SP);

  return long(stackptr) - long(heapptr);
}

これは、各ループのメモリ量です。

1:  4716 *
2:  4716 *
3:  4716 *
4:  4671
5:  4687
6:  4587 *
7:  4736
8:  4587 *
9:  4559
10: 4577
11: 4515
12: 4527
13: 4587 *
14: 4479
15: 4497
16: 4435
17: 4447
18: 4587 *
19: 4399
20: 4417
21: 4355
22: 4367
23: 4587 *
24: 4319

メモリは少なくなっていますが、最初の数ループの後、5番目のループごと4587 Bytesに空きメモリがあります。〜280ループの後、プログラムはメモリ不足になりますが、それまでは5番目のループごとに正確に4587 Bytes空きメモリがあります。この奇妙な動作の原因となる可能性があるものと、メモリリークのないより優れた動的リストを作成する方法を誰かに説明してもらえますか?

アップデート

各ループで、Projectオブジェクトが生成、使用、および削除されます。それはsthを行います。このような:

void sendRequest() {
  // at first it gets some remote data from a server the result is:
  String  names[]  = {"Project 1", "Project 2", "Project 3"};
  boolean states[] = {true, false, true};

  for(int i = 0; i <= projectCount; i++) {
    addProject(names[i], states[i]);
  }
}

// all variables that are not declarated here are declarated in the
// header file of the class
void addProject(String name, boolean state) {
  if (!startProject) {
    startProject = true;

    firstProject.status      = state;
    firstProject.name        = name;
    firstProject.nextProject = NULL;

    ptrToLastProject = &firstProject;
  } else {
    ptrToLastProject->nextProject = new Project();

    ptrToLastProject->nextProject->status      = tempProjectStatus;
    ptrToLastProject->nextProject->name        = tempData;
    ptrToLastProject->nextProject->nextProject = NULL;

    ptrToLastProject = ptrToLastProject->nextProject;
  }
}

void RssParser::resetParser() { 
  delete ptrToLastProject;
  [...]
}
4

2 に答える 2

1

まず、5回の反復ごとにメモリが4587バイトに戻るため、メモリリークは発生していません。

ただし、ここでは興味深いパターンが発生しています。4587バイトになる前に発生する呼び出しの各セットは、常に最後のセットより80バイト少ないことに気付くでしょう。getFreeMemory

それぞれで受信されるデータがますます増えていると推測sendRequestします。その見返りとして、ループを実行するたびに、より多くのメモリを割り当てようとしています。どこかでリリースするのは良いことですが、ある時点で割り当てすぎになります。

1つの可能性は、リクエストデータを上書きするのではなく、追加projectCountしていることです。その後、は常に増加します。

補足として、これに注意してください:

for(int i = 0; i <= projectCount; i++) {
    addProject(names[i], states[i]);
}

配列をループするには、0ベースのインデックスが必要です。状態を確認するi <= projectCountと、バッファがオーバーランしている可能性があります。に3要素がnamesあり、あなたprojectCount3である場合i = 3、アクセスするとどうなりますnames[i]か?

于 2012-08-21T14:57:29.457 に答える
0

プロジェクトのほぼすべての機能について多くの調査と単体テストを作成した後、私は間違いを見つけることができました。

私のresetParser()関数では、私はdelete ptrToLastProject。しかし、このオブジェクトへの他のポインタがあったため、メモリは解放されませんでした。これを関数に追加するとresetParser()、リークが修正されました。

delete firstProject.nextProject;

これは、firstProjectがスタック上にあり、ヒープ上のリストにある他のプロジェクトへのポインターがあるためです。このポインタを削除すると、リスト内の他のすべてのオブジェクトもデストラクタによって削除されます。

于 2012-08-28T12:26:40.997 に答える