シンプル:cvLoadImage()
名前が示すように、イメージ全体をメモリにロードし (10MB のファイルを考えてください) IplImage*
、イメージ データがメモリ内のどこにあるかを示す を返します。
IplImage
代わりに が返された場合、アプリケーションはさらに 10MB のメモリを割り当てて、プログラムのメモリにデータを複製する必要があるため、これは非常に便利です。したがって、データのメモリ アドレスを含むポインターを返すことは、実際には非常に賢明な設計上の決定です。
cvReleaseImage()
このデザインを反映するために、ダブル ポインターを受け取ります。OpenCV v2.3 ソース コードをダウンロードすると、次の場所で実装を確認できますmodules/core/src/array.cpp
。
2979 CV_IMPL void
2980 cvReleaseImage( IplImage ** image )
2981 {
2982 if( !image )
2983 CV_Error( CV_StsNullPtr, "" );
2984
2985 if( *image )
2986 {
2987 IplImage* img = *image;
2988 *image = 0;
2989
2990 cvReleaseData( img );
2991 cvReleaseImageHeader( &img );
2992 }
2993 }
メモリ リソースの実際の解放は、他の 2 つのヘルパー関数によって行われることは明らかです。これらの関数は、ある時点でcvFree()
メモリを解放するために呼び出します。
cvReleaseImage()
ただし、@Nikolai による共有の単純化は正しいです。
編集:あなたのコメントに答えるために。
へのポインターを割り当てて0
malloc()
も、 /で予約されたメモリの割り当てが解除されることはありませんnew
。ポインターが別の場所を指すようになるだけで、この場合はどこにもありません! cvReleaseImage (&img)
意味を理解しましょう。それはすべてから始まります:
IplImage* img = NULL;
ポインター宣言は、通常の変数宣言と同じことを行います。データを格納するために一定量のメモリを割り当てます。上記のような (32 ビット アーキテクチャの) ポインター宣言は、他の変数のアドレスを格納するために 4 バイトのメモリを割り当てます。つまり、ポインタ自体は、宣言された関数内で 4 バイトのメモリを消費します。
呼び出しは、ポインターが指しているデータのアドレスではなく、ポインターcvReleaseImage(&img)
のアドレスを渡します(ここで A-HA の瞬間)。
それでは、残りのコードを分析しましょう。
2985 if( *image ) // does the original pointer points somewhere?
2986 {
// img copies the address of the data pointed by it's cousing image
2987 IplImage* img = *image;
// and handles the deallocation procedure from now own using img.
// By clearing the original pointer,
2988 *image = 0;
// OpenCV allows us to test for it's release
// after cvReleaseImage() executes.
2989
2990 cvReleaseData( img );
2991 cvReleaseImageHeader( &img );
2992 }
したがって、これ*image = 0;
は標準的な手順にすぎないため、後で次のように解放が成功したかどうかを確認できます。
cvReleaseImage (&img);
if (img != NULL)
{
// OOPS! Something went wrong, memory was not released!
}