此代码是不是会导致内存泄漏(Arduino)
Posted
技术标签:
【中文标题】此代码是不是会导致内存泄漏(Arduino)【英文标题】:Can this code cause a memory leak (Arduino)此代码是否会导致内存泄漏(Arduino) 【发布时间】:2012-11-20 10:57:49 【问题描述】:我有一个 arduino 项目,我创建了这个结构:
struct Project
boolean status;
String name;
struct Project* nextProject;
;
在我的应用程序中,我解析一些数据并创建 Project
对象。要将它们放在列表中,每个Project
对象中都有一个指向nextProject
的指针,除了最后一个。这是我添加新项目的代码:
void RssParser::addProject(boolean tempProjectStatus, String tempData)
if (!startProject)
startProject = true;
firstProject.status = tempProjectStatus;
firstProject.name = tempData;
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;
firstProject
是一个私有实例变量,在头文件中定义如下:
Project firstProject;
所以如果实际上没有添加项目,我使用firstProject
添加一个新项目,如果设置了firstProject
,我使用nextProject
指针。
我还有一个reset()
方法可以删除指向项目的指针:
void RssParser::reset()
delete ptrToLastProject;
delete firstProject.nextProject;
startProject = false;
每次解析运行后我调用reset()
问题是使用的内存没有释放。如果我注释掉 addProject
方法,我的记忆就没有问题。谁能告诉我什么可能导致内存泄漏?
【问题讨论】:
在调用reset()
之前可能会抛出异常(例如 operator new
或您的代码的任何部分)
【参考方案1】:
首先,您不需要变量 startProject
- 只需将 firstProject
指针初始化为 NULL,然后像这样编写您的条件:
if (firstProject)
// There is a project, so append the new one.
else
// There is no project, so we need to create a new list.
值FALSE
定义为0,就像NULL。如果 firstProject
为 NULL,则表达式看起来像 if (FALSE)
并在 else
块内继续执行。
所以现在你的reset
-Method 需要释放分配给所有项目的内存,不仅仅是最后一个和第二个项目,就像你的代码那样。
delete ptrToLastProject; // Free last project
delete firstProject.nextProject; // Free the project following to the first one.
这里的问题是:
如果ptrToLastProject == firstProject.nextProject
怎么办?第二个delete
-statement 将释放已释放的内存。
firstProject
永远不会被释放
第二个和最后一个之间的项目永远不会发布。
释放单链表的最好方法是这样的:
Project* pProject = firstProject;
Project* pProjectToDelete;
while (pProject) // As long as the pointer points to something (see the first comment)
pProjectToDelete = pProject;
pProject = firstProject->nextProject;
delete pProjectToDelte;
在这个实现中,你“遍历”列表,释放前面的元素,只要后面有一个元素。如果下一个元素是NULL
,则表示最后一个元素已被释放,循环中断。
最后但同样重要的是,您需要将指针重置为第一个元素(在数据结构方面也称为“锚”):
firstProject = NULL;
这确保addProject
不会尝试将项目附加到NULL
。
【讨论】:
您的 while 循环不正确。在这种情况下,您将访问之前删除的项目。此外,您不会删除第一个项目。您需要一个临时变量来记住当前指针,将pProject
迭代到下一个项目,然后删除临时变量指向的项目。
你是对的,谢谢...我会解决它;)我应该在未来阅读我的答案两次:D
删除 null 在任何符合标准的 C++ 系统上都是无操作的,包括 g++-avr。【参考方案2】:
您的reset
函数需要遍历项目链,而不仅仅是删除第一个和最后一个
【讨论】:
或者让Project的析构函数删除nextProject。不过要小心长“列表”以上是关于此代码是不是会导致内存泄漏(Arduino)的主要内容,如果未能解决你的问题,请参考以下文章