【问题标题】:Cannot delete unsigned char* array无法删除 unsigned char* 数组
【发布时间】:2013-01-26 15:49:50
【问题描述】:

在我的一个对象中,我创建了一个无符号字符数组成员来存储一些图像数据:

    unsigned char* imageData;

在构造函数中我用 new 初始化它:

    MyObject::MyObject()
    {
        int imageSize = 6054400;
        imageData = new unsigned char[imageSize];
    }

imageData 在整个循环过程中被填充。

这个对象(MyObject)直到循环结束才会被删除,但我需要在循环中途删除 imageData。所以我刚刚创建了这个函数:

    void MyObject::DeleteAllMembers
    {
        delete [] imageData;
    }

我在循环结束时调用它:

    theObj.DeleteAllMembers();

问题是每次我的程序到达代码行:

    delete [] imageData;

它崩溃了,留下这个错误信息:

目前我不知道为什么会这样。

我尝试过的一些事情是:

  • 使用 imageSize+1 而不仅仅是 imageSize 来初始化 imageData
  • 将删除命令移至析构函数并手动删除每次循环运行的对象
  • 使用 delete imageData 而不是 delete [] imageData,尽管我相当确定我需要使用 delete []
  • 我在删除imageData = 0 后尝试了它,不幸的是我的程序仍然在delete [] imageData 行崩溃。
  • 我尝试过使用 memset(&imageData, 0, imageSize);,但这给了我访问冲突错误。

每次,程序仍然在同一行崩溃。我知道有人在查看我的代码时在想“你这个白痴,你所要做的就是____________________”。谁能告诉我我做错了什么?

编辑:对不起,我说错了。我每次在loop开始时创建这个对象,在loop结束时被删除,我不知道为什么我在开始和结束时说程序。

【问题讨论】:

  • 你遵守三法则吗?是不是循环中的同一个对象,在这种情况下会发生双释放。
  • 此语句:theObj.DeleteAllMembers; 确实调用DeleteAllMembers。你需要theObj.DeleteAllMembers()
  • 今天我了解到我在输入没有红色下划线来纠正错误的代码方面是多么糟糕。

标签: c++ object memory heap-memory


【解决方案1】:

您可能需要稍微添加以防止多次删除同一指针:

void MyObject::DeleteAllMembers
{
    delete [] imageData;
    imageData = 0; // <-- here
}

【讨论】:

  • @AlokSave 你怎么知道的?
  • 如果你的答案解决了任何问题,多次删除同一个动态指针,你建议的解决方案隐藏了更基本的基本问题,即为什么同一个对象被删除两次.解决方案是找出发生这种情况的原因,而不是让它发生而不是隐藏它。
  • @AlokSave 设计问题和实现问题是两个不同的东西。
  • 这意味着什么?在实现中隐藏设计问题没有多大意义。
  • “没有多大意义”
【解决方案2】:

嗯?

如果你只在构造对象时分配(使用new[]),那么你不能在一个循环中多次delete[]。你只能delete[] 一次,再次将相同的指针传递给delete[] 将失败。

另外,它没有任何意义:如果您只在对象构造时创建一次数组,那么为什么需要多次销毁它?

【讨论】:

    【解决方案3】:

    如果您需要重新使用它,请重置您的缓冲区,而不是在循环中删除它。 以 memset 为例。

    memset(&imageData, 0, imageSize);
    

    然后,当你不再需要它时,删除它。

    【讨论】:

    • memset 在 C++ 中? 不用,谢谢。你也没有发现问题。
    • 然后,有一天,imageData 变成了不同于内置类型的对象,而 你不会注意到。我在现实生活中看到过这种情况,导致生产代码中出现严重错误。改用std::fill,它更能识别类型。 (不过,至少你没有在指针上使用 C 风格的强制转换。)
    • 只是为了记录,std::fill 在 char 上使用 memset。一天可能会发生很多事情。并且可能 std::fill 也无济于事。不过我同意你的评论,但这不是我认为的重点。
    • std::fill 在下面做什么并不重要。
    【解决方案4】:

    你的问题有点不清楚,但有几点:

    • 如果 'imageData' 是 'MyObject' 的成员,那么为什么要从 OUTSIDE 'MyObject' 如此明确地管理它的破坏?

    • 如果“imageData”在“循环”的每次迭代中都被销毁,则必须在再次使用(和销毁)之前再次创建它。

    • “循环”在哪里?如果它在一个属于“MyObject”成员的函数中,或者没有改变您管理“imageData”的方式

    • 如果大小发生变化,您只需在“循环”的每次迭代中删除并重新分配数组。

    • 如果“imageData”最终在“循环”范围内被创建和销毁,为什么它会成为类成员?

    【讨论】:

      【解决方案5】:

      我怀疑你有 违反了Rule of Three

      此问题的最佳解决方案是完全避免它,例如使用std::vector。见“Rule of Zero”。

      class MyObject 
      {
        std::vector<unsigned char> imageData;
        ...
      };
      
      MyObject::MyObject() : imageData(6054400) {}
      
      void MyObject::DeleteAllMembers
      {
        imageData.resize(0);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 1970-01-01
        • 2013-05-16
        • 2012-04-15
        • 1970-01-01
        • 2012-05-06
        相关资源
        最近更新 更多