Простой: cvLoadImage()
, как следует из названия, загружает все изображение в память (рассмотрим файл размером 10 МБ) и возвращает IplImage*
, в котором указано, где находятся данные изображения в памяти.
Это невероятно полезно, потому что если бы оно вернуло IplImage
, нашему приложению нужно было бы выделить еще 10 МБ памяти, дублируя данные в памяти программы!Таким образом, возвращение указателя с адресом памяти данных на самом деле является очень разумным проектным решением.
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 }
Понятно, что фактическое освобождение ресурсов памяти выполняется двумя другими вспомогательными функциями, которые в какой-то моментпозвоните 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!
}