IplImage 構造体ポインタを new/delete する方法
この方法でいいのかなあ?メモリリークしていないのかなあって不安があります.誰か助けてください.
動画中のとある連続したフレーム区間をまとめて処理したかった.cvQueryFrame() で得られる IplImage は,スコープから外れると解放されるため,cvCloneImage() で別に避けておく必要があった.他には構造体ポインタを new/delete できるのか?記述方法は?という疑問が生じた.
テストコード(後述)で検証した.使用した動画ファイルの詳細はこのとおり.
[90frame.avi] 256x256 24Bit 無圧縮 5.00fps 90f 7864.64kb/s [RIFF(AVI1.0)] 00:00:18.000 (18.000sec) / 17,700,984Bytes 真空波動研Lite 081122 / DLL 081122
コード記述について
IplImage 配列について delete が出来なかった(D とマークしたところ).cvCloneImage() で確保した IplImage frame_count 個の解放を image_releaser() に分離した.可読性向上を狙った.先頭ポインタと個数を渡して cvReleaseImage() をさせている.
メモリ使用量の変化を確認した
VC++ のデバッグ実行でメモリ使用量をタスクマネージャで確認した.数値はすべてキロバイト単位である.
タイミング | メモリ使用量 |
---|---|
A | 8808 |
B | 8808 |
C | 26724 |
D | - |
E | 9074 |
new-delete_iplimage_array.exe の 0x102d31ea でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xfdfdfdf1 を読み込み中にアクセス違反が発生しました。
18MB 28MB とを行ったり来たり.
変数 a を使った for ループで images への読込・解放を繰り返したところ,メモリ使用量の増減具合が妙だった.ブレークポイントの位置は #if DO_CAPTURE_LOOP が2回目に現れるところに設定した.
- 8684
- 8700
- 9920
- 26664
- 16848
- 26532
- 14152
- 27088
- 14352
- 26854
テストコード
#include <cv.h> #include <highgui.h> #pragma comment(lib,"cv.lib") #pragma comment(lib,"cxcore.lib") #pragma comment(lib,"highgui.lib") #define DO_CAPTURE_LOOP 1 void image_releaser(IplImage **images, int size) { int i = 0; while( i < size ) { cvReleaseImage(&images[i]); i++; } } int main(void) { const char *in_video_file[] = { "c:/data/video/90frame.avi", }; CvCapture *cap; int frame_count = 90; IplImage **images; IplImage *image; int i; #if DO_CAPTURE_LOOP for(int a = 0; a < 10; a++){ #endif cap = cvCaptureFromAVI(in_video_file[0]); // 失敗するから 90 を代入 // int framecount = (int) cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_COUNT); // A images = new IplImage *[frame_count]; // B for(i = 0; i < frame_count; i++) { image = cvQueryFrame(cap); images[i] = cvCloneImage(image); } // C image_releaser(images, frame_count); // D delete は失敗する // new-delete_iplimage_array.exe の 0x102d31ea でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xfdfdfdf1 を読み込み中にアクセス違反が発生しました。 //delete images [frame_count]; // E cvReleaseCapture(&cap); #if DO_CAPTURE_LOOP } #endif return 0; }