我有一个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;
[...]
}
答案 0 :(得分:1)
首先,你没有泄漏内存,因为在每5次迭代你的记忆恢复到 4587字节
然而,这里出现了一个有趣的模式。您会注意到 之前 比最后一组少80个字节。
我要猜测每个getFreeMemory
收到越来越多的数据,作为回报,您尝试分配更多内存每个都在循环中运行。你在某个地方释放它一切都很好,但是在某些时候你试图分配太多了!
一种可能性是,您追加请求数据,而不是覆盖它,随后sendRequest
会不断增加。
作为旁注,请注意此:
projectCount
循环数组需要 0基于索引。当您检查条件for(int i = 0; i <= projectCount; i++) {
addProject(names[i], states[i]);
}
时,您可能会超出缓冲区。如果i <= projectCount
中有3
个元素,而names
为projectCount
,那么当3
访问i = 3
时会发生什么?
答案 1 :(得分:0)
经过大量研究并为项目的几乎所有功能编写单元测试后,我才能找到错误。
在我的resetParser()
函数中,我只做了delete ptrToLastProject
。但是还有一个指向此对象的指针,因此内存未被释放。将此添加到resetParser()
函数可修复泄漏。
delete firstProject.nextProject;
原因是因为firstProject
在堆栈上,指向堆上列表中的其他项目。当我删除这个指针时,列表中的所有其他对象也会被它们的析构函数删除。