2016-05-06 8 views
0

Qtで画像データのシーケンスを保存しようとすると問題が発生します。ここ QtがQImageが正しく読み込まれていると誤って認識しています

は、問題を示すコードの一部である:第1ループに

#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ベクトルにビットマップを置きます。 2番目のループでは、各フレームのピクセルを読み取るだけです。

問題は、ヒープメモリがいっぱいになっても、プログラムは最初のループを通って不平を言わずに進むことです。プログラムの出力によって示されるようにその結果、私は、第二のループでクラッシュを取得:

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

問題を再現するには、以下のグレースケール画像を使用することができ、あなたが値を変更する必要があるかもしれませんnFramesのメモリ容量によって異なります。

私の質問は:メモリがいっぱいになったかどうかを検出する方法で最初のループにデータをロードするにはどうしたらいいですか?私は必ずQImageオブジェクトをメモリ内に保持する必要はなく、imagesベクトルのデータだけを保持します。全ての

Sample image

+3

Btwでは、ヒープに 'QImage'を作成する必要はありません。それは牛をサポートします。 –

答えて

1

ファーズは、最初のループは削除されないimgオブジェクトのbecouseメモリリークを有しています。 Qtのドキュメントから

UCHAR *最初のピクセルデータへのポインタを返す

QImageの::ビット()

。この は、scanLine(0)と同等です。

QImageは暗黙的なデータ共有を使用しています。この関数は、共有ピクセルデータの深いコピー を実行し、このQImageが現在の戻り値を使用する唯一の であることを保証します。

したがって、imgを安全に削除することができます。メモリがいっぱいになると

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

は、オペレータnewは、このようなQImageオブジェクトを作成するかどうかをチェックすることができます検出するには:

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

'' img''を削除することはできません。 '' images''に格納されているポインタはどこにも指しておらず、2番目のループをクラッシュさせます。 – mimo

+0

また、if(!img) 'はメモリの問題を捕まえません。このコードはあなたのために機能しますか?私はDebianを試しました。 – mimo

0

部分的な答え:

最初のループを置き換えることができ以下:

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->bits()が指し示すデータのコピーが作成されます。 (Btw、これにより、最初のforループの最後でQImageを削除できるようになりました)メモリ不足の場合、ループ内のstd :: bad_allocエラー。

しかし、これでは十分ではありません。nFramesが、プログラムによって取られた最大メモリが限界に近い値に設定されている(または、これが実行されている間に別のプログラムがメモリを解放する)場合、考えられる問題と思われます。 私はまだimg.bits()が正確なデータへのポインタを返すという保証はないということです。

関連する問題