2012-11-20 42 views
0

我有一个Arduino的项目,我创造了这个结构:这个代码可以导致内存泄漏(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方法,我的记忆没有问题。有人可以告诉我什么可能导致内存泄漏?

+0

在调用'reset()'之前可能会抛出异常(例如操作符'new'或任何部分代码) – Ruu

回答

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 -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; 
} 

在此实现你的“行走”在列表中,释放predecessing元素,只要有一个元素如下。如果下一个元素是NULL,则最后一个元素已被释放,并且循环中断。

最后但并非最不重要的,你需要将指针复位到第一个元素(也称为数据结构的术语“锚”):

firstProject = NULL; 

这保证addProject不会尝试追加的项目到NULL

+1

您的while循环不正确,但请注意长“列表”。在这种情况下,您将访问以前删除的项目。此外,您不要删除第一个项目。您需要一个临时变量来记住当前指针,将'pProject'迭代到下一个项目,然后删除由temp变量指向的项目。 –

+0

你是对的,谢谢你...我会修复它;)我应该在将来两次阅读我的答案:D – Carsten

+0

删除null是任何标准兼容C++系统上的禁用操作,包括g ++ - avr。 –

1

reset函数需要遍历下来的项目链,而不仅仅是删除第一个和最后的

+0

或者使项目的析构函数删除nextProject。虽然 – TeaOverflow