【问题标题】:Qt wrongly thinks QImage is loaded properlyQt 错误地认为 QImage 已正确加载
【发布时间】:2016-05-06 06:58:55
【问题描述】:

我在尝试使用 Qt 存储一系列图像数据时遇到问题。

这是一段显示问题的代码:

#include <vector>
#include <iostream>
#include <QImage>

...

const int nFrames = 1000;
std::vector<int> sizes(nFrames);
std::vector<uchar*> images(nFrames);
for (int k = 0; k < nFrames; k++)
{
    QImage *img = new QImage("/.../sample.png");
    uchar *data = img->bits();
    sizes.at(k) = img->width() * img->height();
    images.at(k) = data;
}

std::cout << "Data loaded \"successfully\"." << std::endl;

for (int k = 0; k < nFrames; k++)
{
    std::cout << k << ": " << (int) (images.at(k)[0]) << std::endl;
}

在第一个循环中,程序加载 QImage 对象并将位图放入 images 指针向量中。在第二个循环中,我们只读取每一帧的一个像素。

问题在于,即使堆内存已满,程序也会毫无问题地继续执行第一个循环。结果,我在第二个循环中遇到了崩溃,如程序的输出所示:

Data loaded "successfully".
0: 128
1: 128
2: 128
...
192: 128
[crash before hitting 1000]

要重现问题,您可以使用下面的灰度图,您可能需要更改nFrames 的值,具体取决于您拥有的内存量。

我的问题是:如何在第一个循环中加载数据,以便检测内存是否已满?我不一定需要将 QImage 对象保留在内存中,而只需要将images 向量的数据。

【问题讨论】:

  • 顺便说一句,没有必要在堆上创建QImage。它支持COW。

标签: c++ qt memory heap-memory qimage


【解决方案1】:

首先,第一个循环有内存泄漏,因为img 对象没有被删除。

来自 Qt 文档:

uchar * QImage::bits()

返回指向第一个像素数据的指针。这个 相当于scanLine(0)。

请注意,QImage 使用隐式数据共享。这个函数执行一个 共享像素数据的深拷贝,从而确保此 QImage 是 唯一使用当前返回值的。

所以你可以安全地删除img at and of loop。

    ....
    images.at(k) = data;
    delete img;
}

要检测内存是否已满,您可以检查运算符 new 是否像这样创建 QImage 对象:

QImage *img = new QImage("/.../sample.png");
if(!img) {
    //out of memory
}

【讨论】:

  • 您不能delete img,因为存储在images 中的指针将指向任何地方并导致第二个循环崩溃。
  • 另外,if (!img) 没有捕捉到内存问题。这些代码在你那正常吗?我在 Debian 上试过。
【解决方案2】:

部分回答:

第一个循环可以替换为:

for (int k = 0; k < nFrames; k++)
{
    QImage *img = new QImage("/.../sample.png");
    sizes.at(k) = img->width() * img->height();
    uchar *data = new uchar[sizes.at(k)];
    std::copy(img->bits(), img->bits() + sizes.at(k), data);
    images.at(k) = data;
    delete img;
}

这会在images.at(k) 中创建img-&gt;bits() 指向的数据的副本。 (顺便说一句,这允许现在在第一个 for 循环结束时删除 QImage。)如果内存不足,循环中的 std::bad_alloc 错误。

但是,这还不够好。我怀疑当 nFrames 设置为某个值以使程序占用的最大内存接近限制时(或者当另一个程序在运行时释放内存)。 我担心的是我仍然不能保证img.bits() 返回一个指向准确数据的指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    相关资源
    最近更新 更多