此代码是不是会导致内存泄漏(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)的主要内容,如果未能解决你的问题,请参考以下文章

分析 ThreadLocal 内存泄漏问题

此代码是否会导致JavaScript中的内存泄漏

内存泄漏与垃圾回收机制

OpenGL VBO 会泄漏内存吗?

不关闭我的 JDBC PreparedStatements 是不是会导致内存泄漏?

万恶的前端内存泄漏及万善的解决方案