Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
6797 Discussions

"*** glibc detected *** double free or corruption (!prev)" message when using ippsFree()

eren
Beginner
814 Views
Hi all,

I am running IPP 5.0 on a Dual-Xeon machine with Suse 9.3 installed. I am trying to build an application that looks for connected components on an image and stores information about them in a C++ vector if they have more than a predefined number of edge pixels (detected using a Laplacian of Gaussian filter since I could not get ippiCanny to work after all...). The vector contains instances of a structure called evidence which I have defined as follows:

typedef struct {
	int numPixels;
	Ipp32f *pixelRows;
	Ipp32f *pixelColumns;
	Ipp32f meanVector[2];
	Ipp32f covarianceMatrix[4];
} evidence;
As I process connected components, I store the coordinates of their edge pixels in temporary buffers called rows and cols, which I at the end copy to the pixelRows and pixelColumns members of the new instance of evidence. However, when I try to free the memory associated with rows and cols, I get the dreaded "*** glibc detected *** double free or corruption (!prev)" error message and I am at a loss as to why this happens or how I should handle it. As I understand from looking around the net, this error message occurs when you try to release some memory that has been already freed, but this is definitely not the case with my code. I am attaching the part of the code that creates the problem:

// Find connected components on the dilated edge map and match them to undilated one
int p, q, floodFillBufferSize, edgePixels, foundEvidence = 0, value = 1;
IppiConnectedComp region;
	
ippiFloodFillGetSize(frameSizeDec, &floodFillBufferSize);
Ipp8u *floodFillBuffer = ippsMalloc_8u(floodFillBufferSize);
	
for (i = 0; i < frameSizeDec.height; i++)
{
	for (j = 0; j < frameSizeDec.width; j++)
	{
		if (*(temp1 + i * step1_8u + j) == IPP_MAX_8U)
		{
			IppiPoint seed = {j, i};
			ippiFloodFill_8Con_8u_C1IR(temp1, step1_8u, frameSizeDec, seed, value, &region, floodFillBuffer);
								
			IppiPoint corner = {region.rect.x, region.rect.y};
			IppiSize regionSize = {region.rect.width, region.rect.height};
				
			ippiCountInRange_8u_C1R(edges + corner.y * step1_8u + corner.x, step1_8u, regionSize, &edgePixels, IPP_MAX_8U, IPP_MAX_8U);
								
			if (edgePixels >= EDGE_PIXELS_PER_EVIDENCE)
			{
				foundEvidence++;
				value++;

Ipp32f *rows = ippsMalloc_32f(2 * edgePixels); Ipp32f *cols = ippsMalloc_32f(2 * edgePixels); Ipp32f *minRows = ippsMalloc_32f(regionSize.width); Ipp32f *maxRows = ippsMalloc_32f(regionSize.width); Ipp32f *minCols = ippsMalloc_32f(regionSize.height); Ipp32f *maxCols = ippsMalloc_32f(regionSize.height); ippsSet_32f(-1.0, minRows, regionSize.width); ippsSet_32f(IPP_MAXABS_32F, maxRows, regionSiz e.width); ippsSet_32f(-1.0, minCols, regionSize.height); ippsSet_32f(IPP_MAXABS_32F, maxCols, regionSize.height); // Find minimum and maximum column where there is an edge for each row for (p = 0; p < regionSize.height; p++) { for (q = 0; q < regionSize.width; q++) { if (*(edges + (corner.y + p) * step1_8u + (corner.x + q))) { *(minCols + p) = corner.x + q; break; } } for (q = regionSize.width - 1; q >= 0 ; q--) { if (*(edges + (corner.y + p) * step1_8u + (corner.x + q))) { *(maxCols + p) = corner.x + q; break; } } } // Find minimum and maximum row where there is an edge for each column for (q = 0; q < regionSize.width; q++) { for (p = 0; p < regionSize.height; p++) { if (*(edges + (corner.y + p) * step1_8u + (corner.x + q))) { *(minRows + q) = corner.y + p; break; } } for (p = regionSize.height - 1; p >= 0 ; p--) { if (*(edges + (corner.y + p) * step1_8u + (corner.x + q))) { *(maxRows + q) = corner.y + p; break; } } } // Populate row and column vectors edgePixels = 0; // Traverse rows ippsMax_32f(minCols, 2, &max); ippsMin_32f(maxCols, 2, &min); if ((max >= 0.0) && (min < IPP_MAXABS_32F)) // There is an edge in the first row { ippsSet_32f((Ipp32f)(corner.y), rows + edgePixels, 2); *(cols + edgePixels++) = max; *(cols + edgePixels++) = min; } for (p = 1; p < regionSize.height - 1; p++) { ippsMax_32f(minCols + p - 1, 3, &max); ippsMin_32f(maxCols + p - 1, 3, &min); if ((max >= 0.0) && (min < IPP_MAXABS_32F)) // There is an edge in the p-th row { ippsSet_32f((Ipp32f)(corner.y + p), rows + edgePixels, 2); *(cols + edgePixels++) = max; *(cols + edgePixels++) = min; } } ippsMax_32f(minCols + regionSize.height - 2, 2, &max); ippsMin_32f(maxCols + regionSize.height - 2, 2, &min); if ((max >= 0.0) && (min < IPP_MAXABS_32F)) // There is an edge in the last row { ippsSet_32f((Ipp32f)(corner.y + regionSize.height - 1), rows + edgePixels, 2); *(cols + edgePixels++) = max; *(cols + edgePixels++) = min; } // Traverse columns ippsMax_32f(minRows, 2, &max); ippsMin_32f(maxRows, 2, &min); if ((max >= 0.0) && (min < IPP_MAXABS_32F)) // There is an edge in the first column { ippsSet_32f((Ipp32f)(corner.x), cols + edgePixels, 2); *(rows + edgePixels++) = max; *(rows + edgePixels++) = min; } for (q = 1; q < regionSize.width - 1; q++) { ippsMax_32f(minRows + q - 1, 3, &max); ippsMin_32f(maxRows + q - 1, 3, &min); if ((max >= 0.0) && (min < IPP_MAXABS_32F)) // There is an edge in the q-th column { ippsSet_32f((Ipp32f)(corner.x + q), cols + edgePixels, 2); *(rows + edgePixels++) = max; *(rows + edgePixels++) = min; } } ippsMax_32f(minRows + regionSize.width - 2, 2, &max); ippsMin_32f(maxRows + regionSize.width - 2, 2, &min); if ((max >= 0.0) && (min < IPP_MAXABS_32F)) // There is an edge in the last column { ippsSet_32f((Ipp32f)(corner.x + regionSize.width - 1), cols + edgePixels, 2); *(rows + edgePixels++) = max; *(rows + edgePixels++) = min; } // Model evidence with a Gaussian evidence newEvidence; newEvidence.numPixels = edgePixels; newEvidence.pixelRows = ippsMalloc_32f(edgePixels); ippsCopy_32f(rows, newEvidence.pixelRows, edgePixels); newEvidence.pixelColumns = ippsMalloc_32f(edgePixels); ippsCopy_32f(cols, newEvidence.pixelColumns, edgePixels); CalulateGaussian2D(newEvidence.pixelColumns, newEvidence.pixelRows, edgePixels, newEvidence.meanVector, newEvidence.covarianceMatrix); frameEvidence.push_back(newEvidence); cout << rows << endl; ippsFree(rows); cout << cols << endl; ippsFree(cols); cout << minRows << endl; ippsFree(minRows); cout << maxRows << endl; ippsFree(maxRows); cout << minCols << endl; ippsFree(minCols); cout << maxCols << endl; ippsFree(maxCols); } } } }

The CalculateGaussian2D function returns the mean vector and covariance matrix of a two-dimensional Gaussian that describes the row and column coordinates of the edge pixels. The undilated edge map of the image is stored in edges, while the dilated one in temp1.

If I run the program as is, I get the following:

0x433f8ec0
*** glibc detected *** double free or corruption (!prev): 0x433f8ea0 ***
Aborted

The first line is the memory location of the rows pointer (produced by cout << rows << endl;). What is interesting is that the problem seems to occur in a memory location prior to the start of rows; in fact the difference between the two memory locations fluctuates between 8 and 32 bytes (as is the case in this example). I am guessing that this fluctuation has something to do with ippsMalloc() allocating things along a 32-byte boundary, but that's as far as I can go, and this nonetheless doesn't seem to explain the "double free" problem. I should also point out that if I comment out the two for loops in the "Populate row and column vectors" section of the code (both for the row and the column traversal), the code will execute just fine without any memory problems, and this has me even more baffled...

Any ideas or suggestions are highly welcome as resolving this issue will certainly make my summer vacations much more enjoyable...

Andreas.
0 Kudos
0 Replies
Reply