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

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

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.

1 contribution / 0 nouveau(x)
Reportez-vous à notre Notice d'optimisation pour plus d'informations sur les choix et l'optimisation des performances dans les produits logiciels Intel.