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回目に現れるところに設定した.

  1. 8684
  2. 8700
  3. 9920
  4. 26664
  5. 16848
  6. 26532
  7. 14152
  8. 27088
  9. 14352
  10. 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;
}