1

我有一个 arduino 程序,我想将数据存储在动态列表中。为此,我使用以下内容struct

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

Project现在我根据外部数据生成动态数量的对象。我只有第一个Project对象作为变量,其余的我可以通过nextProject指针获得。

对象的生成每分钟Project都在 my 中完成。loop问题是我有时会失去记忆,直到它变空。
这就是我的主循环的样子:

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

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

parseTimer是一个非阻塞延迟函数,true每 60 秒返回一次;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;
  [...]
}
4

2 回答 2

1

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

然而,这里发生了一个有趣的模式。您会注意到,您拥有4587 个字节之前发生的每组调用总是比最后一组少80 个字节。getFreeMemory

我将猜测每个 接收到的数据越来越多sendRequest,作为回报,您试图在每次循环中分配更多内存。你在某个地方发布它很好,但在某些时候你试图分配太多!

一种可能性是您正在附加请求数据,而不是覆盖它,然后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 回答