0

stlコンテナに保存されているopencvイメージを解放するのに問題があります。私はカメラから最後の数フレームを保存するシステムを開発しています。画像を保存するためのコンテナが必要です。しかし、イテレータを使用して画像にアクセスして解放しようとすると、問題が発生します。このような。

deque<IplImage> ImageQue;
IplImage * temp=cvCreateImage(cvSize(30, 30), 8, 3);
ImageQue.push_back(*temp);
deque<IplImage>::iterator it=ImageQue.begin();
//temp and temp2 pointing different mem 
IplImage * temp2=&*it;
//this goes wrong. execption at memory location.
cvReleaseImage(&temp2);

これを試してみたら。

IplImage * try1=cvCreateImage(cvSize(30, 30), 8, 3);
//try1 and try2 are pointing the same mem.
IplImage * try2=&*try1;
//things alright here.
cvReleaseImage(&try2);

問題はここにあると思います。deque :: iterator it = ImageQue.begin(); IplImage * temp2 =&* it;

これについて何か考えはありますか?または、stlコンテナでイメージをリリースしたい場合の提案ですか?

4

3 に答える 3

2

ポインタの間接参照を少し混ぜ合わせているようです。これを行わないことはおそらく良い考えです:

deque<IplImage> ImageQue; 
IplImage * temp=cvCreateImage(cvSize(30, 30), 8, 3); 
ImageQue.push_back(*temp); 

おそらくポインタのコンテナを使用する必要があります(インスタンス名に先頭の大文字は使用しないでください)。

deque<IplImage*> imageQueue; 
imageQueue.push_backcvCreateImage(cvSize(30, 30), 8, 3));
// ...
auto itr = imageQueue.begin();
IplImage* temp = *itr;
cvReleaseImage(&temp);

ある種のこと。さらに重要なのは、おそらく...そのように画像を破棄する場合は、ダングリングポインターのキューが必要ないため、最初にコンテナーから画像を取り出す必要があります。

IplImage* temp  = imageQueue.front();
imageQueue.pop_front();
cvReleaseImage(&temp);

ある種のスマートポインタ(寿命の終わりにIplImageを自動的に解放する)の使用を検討することもできます...最近のバージョンのOpenCVには、この種の機能に適したC ++ APIが含まれていませんか?std::shared_ptr適切なカスタム削除機能があれば、Aも機能する可能性があります。

于 2012-06-13T08:04:18.483 に答える
1

あなたがやろうとしているように、CインターフェースIplImageが値でコピーされるのが好きだとは思いません。値のセマンティクスで動作するC++コンテナーを使用する場合は、のコンテナーを使用するIplImage*か、さらに良いことに、RAIIを使用してリソースのコピーと解放を処理するC++インターフェイスのcv:: Matを使用する必要があります(つまり、リリースについて心配する必要はありません)。

于 2012-06-13T07:55:59.380 に答える
0

C++11ではstd::shared_ptrを使用でき、C++03では同等のBoostを使用できます。

オブジェクトのshared_ptrをstlコンテナに格納できますが、削除者を指定する必要があります(デフォルトは演算子deleteです)。

shared_ptrのコンストラクターで、ポインターの削除者を割り当てることができます。あなたの場合、cvReleaseImage関数。

Boostのドキュメントから:

テンプレートshared_ptr(Y * p、D d); テンプレートshared_ptr(Y * p、D d、A a);

Requirements: p must be convertible to T *. D must be CopyConstructible. 
              The copy constructor and destructor of D must not
              throw. The expression d(p) must be well-formed, must not invoke
              undefined behavior, and must not throw exceptions. A must be an
              allocator, as described in section 20.1.5 (Allocator requirements) of
              the C++ Standard.

Effects: Constructs a shared_ptr that owns the pointer p and the deleter d. 
         The second constructor allocates memory using a copy of a.

Postconditions: use_count() == 1 && get() == p.

Throws: std::bad_alloc, or an implementation-defined 
        exception when a resource other than memory could not be obtained.

Exception safety: If an exception is thrown, d(p) is called.

Notes: When the the time comes to delete the object pointed to by p, 
       the stored copy of d is invoked with the stored copy of p as an
       argument.

[カスタムデロケーターを使用すると、shared_ptrを返すファクトリ関数を使用して、ユーザーをメモリ割り当て戦略から隔離できます。デアロケータはタイプの一部ではないため、割り当て戦略を変更しても、ソースまたはバイナリの互換性が損なわれることはなく、クライアントの再コンパイルも必要ありません。たとえば、「no-op」デアロケータは、shared_ptrを静的に割り当てられたオブジェクトに返す場合に役立ちます。他のバリエーションでは、shared_ptrを別のスマートポインタのラッパーとして使用できるため、相互運用性が向上します。

カスタムデロケーターのサポートは、大きなオーバーヘッドを課しません。その他のshared_ptr機能では、引き続きデアロケーターを保持する必要があります。

Dのコピーコンストラクターがスローしないという要件は、値の受け渡しに由来します。コピーコンストラクターがスローすると、ポインターがリークされます。要件を削除するには、パスバイ(定数)参照が必要です。

参照渡しの主な問題は、右辺値との相互作用にあります。const参照は引き続きコピーを引き起こす可能性があり、const operator()が必要になります。非定数参照は、右辺値にまったくバインドされません。この問題の良い解決策は、N1377/N1385で提案されている右辺値参照です。]

于 2012-06-13T08:04:41.583 に答える