c++ - 嵌套的 QVector 指针内存处理

标签 c++ memory-leaks windows-7 qt5

我继承了一个庞大的 Qt5 项目,其中累积的内存泄漏正在成为一个严重的问题。 (是的,内存泄漏应该很少被容忍,但在现实生活中预算和时间限制...)。

此 GUI 将图像数据读取到体素类的对象中,以图形方式显示。数据来自文件或缓冲区(如果实时获取)并存储为嵌套 qvector,即:

QVector < QVector <Voxel *> > cVoxel;

当从文件中读取图像时,cVoxel 使用 QVector.resize(0) 进行初始化。

cVoxel.resize(0);

当打开保存到文件的图像时,会创建一个本地 Voxel 指针并将其推送到 cVoxel 的末尾,每个像素一次,因此循环所有行和列:

for (iRow = 0; iRow < nRows; ++iRow)
{
   for (iCol = 0; iCol < nCols; ++iCol)
   {
      Voxel *v = new Voxel;
      cVoxel[iRow].push_back(v);
      // Code for reading data into cVoxel removed here
      ...
   }
}

感谢下面的有用评论,我现在通过在我的 CTOR 中嵌套销毁 cVoxel QVector,在 Windows 任务管理器中看到内存使用减少方面取得了一些成功。沿着:

for (iRow = 0; iRow < nRows; iRow++)
{
    for (iCol = 0; iCol < nCols; iCol++)
    {
        delete cVoxel[iRow][iCol];
    }
}

理想情况下,主要重写是最好的解决方案。但在现实世界中,我将不得不尝试修复更大的漏洞,并希望这就足够了,直到有足够的资源可用于更理想的解决方案。

  • 我已经查看了 Voxel 本身的内存泄漏,但那里没有什么明显的。
  • 我的研究表明,查看 Windows 任务管理器的内存消耗并不完全可靠(Win7 不是实时操作系统......),但如果打开文件会使应用程序内存消耗从 16M 增加到 81.5M , 那么如果 cVoxel 中分配的内存被成功释放,肯定会有一些内存减少?如果我继续打开和关闭图像,应用程序的内存消耗会以类似的步骤不断增加。关闭任何/所有打开的图像后它永远不会减少。
  • 现在,没有尝试释放分配给(使用 new 运算符)给 cVoxel 的任何内存。我尝试了几种方法(并阅读以了解更多信息),但到目前为止运气不佳。
  • QVector 非常擅长处理它自己的内存处理,但我坚持使用这个嵌套的 QVector 设置,简单地依赖 QVector 的 squeeze()、resize() 或类似方法只会泄漏内存(这已经是项目中其他变量的情况。我已经通过 Visual Leak Detector 运行该项目,所以我知道哪些是严重的罪魁祸首,哪些是小鱼)

----编辑----

对于下面乱七八糟的临时评论表示歉意,但这肯定会帮助我减少内存泄漏(希望在适当的时候完全停止......)。

我在上面进行了在线编辑(希望)使这篇文章更清晰,并删除了我最好的案例工作,因为它对内存泄漏没有影响。上面的重大改动是 (2) 斜体的简短段落。

我还需要调查@richardcitter (sp?) 多态相关的建议。

--- EDIT3 ---

删除了 Edit2,单独发布了那个(新)问题 here .

此外,我非常有信心下面的答案应该可以解决这个问题 - 我只需要弄清楚如何使用 qvector.resize() 或找到解决方法。

最佳答案

很难在注释中格式化代码,所以我将其添加为答案,即使它可能无法解决您的问题。无论如何,评论的时间也相当长。

要解决未定义的行为并正确确保您不需要进行任何额外分配,您可以预先分配 vector 中的元素数量。当您调用 resize(0) 时,您已经这样做了,但是您不是设置您真正需要的大小,而是将大小设置为零,使 vector 为空。

我建议改为这样:

第一次使用std::unique_ptr正如 Richard Critten 所建议的那样:

QVector < QVector < std::unique_ptr <Voxel> > > cVoxel;

如果 Qt 有自己独特的指针类型,您可以改用它。

然后当你创建你使用resize设置 vector 的实际大小:

cVoxel.resize(nRows);

然后您可以在 vector 中使用普通索引。也设置内部 vector 的大小:

for (iRow = 0; iRow < nRows; ++iRow)
{
   cVoxel[iRow].resize(nCols);  // Resize to the number of columns

   for (iCol = 0; iCol < nCols; ++iCol)
   {
      cVoxel[iRow][iCol].reset(new Voxel);  // Create the actual Voxel object

      // Code for reading data into cVoxel here
      ...
   }
}

由于您使用 std::unique_ptr(或 Qt 等价物),一旦对象被释放,由 std::unique_ptr 对象管理的内存将自动释放毁了。因此,当 cVoxel vector 超出范围或以其他方式被破坏时,不再有内存泄漏,您的 Voxel 对象也将如此。

关于c++ - 嵌套的 QVector 指针内存处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48167985/

相关文章:

c++ - .begin() 和 .end() 的意义何在?

c# - 内存溢出 : Having an increasing number of Microsoft. CSharp.RuntimeBinder.Semantics

list - 为什么 `list.Remove()` 试图明确避免内存泄漏?

c++ - MPI 警告 : Program exiting with outstanding receive requests

c++ - 函数声明应该包含参数名称吗?

linux - python 脚本的 pmap 高内存使用率

windows - 添加/删除程序列表的重复数据删除和过滤 (VBScript)

html - 从本地网页运行程序

python - 如何在没有窗口的情况下将图像直接传输到屏幕?

c++ - 未解析为候选容器的模板运算符模板