指向自身的Arduino结构泄漏了内存

时间:2012-08-21 13:11:13

标签: c++ memory-leaks struct arduino

我有一个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();
  }
}

parseTimer是一个非阻塞延迟函数,每60秒返回true; sendRequest生成Project个对象)

我测量记忆的方法:

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个对象。它确实......像这样:

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;
  [...]
}

2 个答案:

答案 0 :(得分:1)

首先,你没有泄漏内存,因为在每5次迭代你的记忆恢复到 4587字节

然而,这里出现了一个有趣的模式。您会注意到 之前 比最后一组少80个字节。

我要猜测每个getFreeMemory收到越来越多的数据,作为回报,您尝试分配更多内存每个都在循环中运行。你在某个地方释放它一切都很好,但是在某些时候你试图分配太多了!

一种可能性是,您追加请求数据,而不是覆盖它,随后sendRequest会不断增加。

作为旁注,请注意

projectCount

循环数组需要 0基于索引。当您检查条件for(int i = 0; i <= projectCount; i++) { addProject(names[i], states[i]); } 时,您可能会超出缓冲区。如果i <= projectCount中有3个元素,而namesprojectCount,那么当3访问i = 3时会发生什么?

答案 1 :(得分:0)

经过大量研究并为项目的几乎所有功能编写单元测试后,我才能找到错误。

在我的resetParser()函数中,我只做了delete ptrToLastProject。但是还有一个指向此对象的指针,因此内存未被释放。将此添加到resetParser()函数可修复泄漏。

delete firstProject.nextProject;

原因是因为firstProject在堆栈上,指向堆上列表中的其他项目。当我删除这个指针时,列表中的所有其他对象也会被它们的析构函数删除。