嵌套的 QVector 指针内存处理
Nested QVector pointer memory handling
我继承了一个重要的Qt5项目,其中累积内存泄漏正成为一个严重的问题。(是的,内存泄漏应该很少被容忍,但有现实生活中的预算和时间限制......
此 GUI 将图像数据读入体素类的对象中,以图形方式显示。数据来自文件或缓冲区(如果实时获取),并存储为嵌套 qvector,即:
QVector < QVector <Voxel *> > cVoxel;
从文件中读取映像时,使用QVector.resize(0)
初始化cVoxel
。
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() 或类似只会泄漏内存(项目中的其他变量已经如此)。我已经通过视觉泄漏检测仪运行了该项目,所以我有一个想法,哪些是严重的罪魁祸首,哪些是小鱼)
----编辑----
为下面凌乱的临时评论道歉,但这肯定会帮助我减少内存泄漏(希望在适当的时候完全停止
......我已经在上面进行了内联编辑,以(希望)使这篇文章更清晰,并删除了我最好的案例努力,因为它对内存泄漏没有影响。上述重大改动是(2)斜体字的简短段落。
我还需要调查@richardcitter(sp?)多态性相关的建议。
--- 编辑3 ---
删除了 Edit2,在此处单独发布了该(新)问题。
另外,我很有信心下面的答案应该可以解决这个问题 - 我只需要弄清楚如何使用qvector.resize()
或找到解决方法。
很难在注释中格式化代码,因此即使它可能无法解决您的问题,我也会将其添加为答案。无论如何,评论也相当长。
要解决未定义的行为并正确确保不需要进行任何额外的分配,您可以预分配向量中的元素数。当你调用resize(0)
时,你已经这样做了,但是你没有设置你真正需要的大小,而是将大小设为零,你让向量为空。
我会建议这样的东西:
第一次使用std::unique_ptr
Richard Critten建议的:
QVector < QVector < std::unique_ptr <Voxel> > > cVoxel;
如果Qt有自己独特的指针类型,你可以改用它。
然后,当您创建 使用resize
来设置矢量的实际大小时:
cVoxel.resize(nRows);
然后,您可以在向量中使用纯索引。同时设置内部向量的大小:
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
向量超出范围或以其他方式被破坏时,不会再发生内存泄漏,您的Voxel
对象也会泄漏。
@SomeProgrammerDude:你让我9/10走向解决方案。我不知道我应该编辑您的答案还是使用它,所以版主请相应地编辑。
正如在一篇相关的SO帖子中所概述的那样,我最终决定反对智能指针。上面的解决方案(对我来说)引入了编译器尝试引用已删除函数的问题。否则,只需进行一些修改即可
:QVector < QVector <Voxel *> > cVoxel;
初始化:
cVoxel.resize(0);
内存分配:
{
for (int i = 0; i < rows; ++i)
{
cVoxel.push_back( QVector <Voxel *> () );
for (int j = 0 ; j < cols ; ++j)
{
Voxel *v = new Voxel;
cVoxel[i].push_back(v);
}
}
}
最后DTOR释放内存:
int iRow, iCol;
for (iRow = 0; iRow < rows; iRow++)
{
for (iCol = 0; iCol < cols; iCol++)
{
delete cVoxel[iRow][iCol];
}
}
- 开放 CV 中的动态内存分配,用于视频处理
- 是否可以通过每次在内存中仅保存一个平铺来处理完整的平铺 tiff 图像?
- 如何处理堆内存垃圾?
- 如何处理以下代码中的内存分配错误
- 将使用 4 或 8 个对齐规则将加载处理到内存中
- 错误 在测试.exe 0x76C9FD62时出现未经处理的异常:Microsoft C++异常:内存位置0x006FF8
- 当有大量内存分配时,如何处理C++编程中的异常
- 在 cplex c++ 音乐会 api++ 中处理非常大的问题而不会耗尽内存
- 如何在处理C++字符串时使用内存集
- QT-如何处理对话框的内存管理
- 通过函数来处理内存 - 这是正确的
- 如何在Qt中处理子类中的动态内存分配
- 如何在将指针传递给库函数时处理内存管理
- 嵌套的 QVector 指针内存处理
- 内存处理问题
- C++std::string内部内存处理
- 错误:C++文字内存处理错误
- 具有动态分配内存的类的内存处理
- 异常安全的COM内存处理
- 内存处理(即函数发布)如何与 Direct3D 配合使用