此代码是否会导致内存泄漏(Arduino)

时间:2012-11-20 10:57:50

标签: c++ memory memory-leaks arduino avr-gcc

我有一个arduino项目,我创建了这个结构:

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

在我的应用程序中,我解析了一些数据并创建了Project个对象。要将它们放在列表中,每个nextProject对象中都有一个指向Project的指针。这是我添加新项目的代码:

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方法,那么我的记忆就没有问题了。有人可以告诉我什么可能导致内存泄漏?

2 个答案:

答案 0 :(得分:3)

首先,您不需要变量startProject - 只需使用NULL初始化firstProject指针,然后写下您的条件:

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 - 方法需要释放为所有项目分配的内存,而不仅仅是最后一个和第二个项目,就像你的代码一样。

delete ptrToLastProject; // Free last project
delete firstProject.nextProject; // Free the project following to the first one.

这里的问题是:

  • 如果ptrToLastProject == firstProject.nextProject怎么办?第二个delete - 语句将释放已释放的内存。
  • 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

答案 1 :(得分:1)

您的reset函数需要迭代项目链,而不仅仅是删除第一个和最后一个