parallel_for function causes memory leaks (sometimes)
I'm making a simple native MFC application and I'm using th Concurrency namespace to perform a simple parallel program (drawing a Mandelbrot set). The program is very very basic so far, clicking one button draws in parallel, the other draws in serial. The serial execution function is very basic and draws the right picture. As does the parallel execution function, however when running the debug build and exiting the program, the output tells me there is a memory leak.
Here's the code:
void CMandelbrotView::DrawSetParallel() {
// Get client area dimension which will be the image size
RECT rect;
GetClientRect(&rect);
//GetClientRect(pDC, &rect);
int imageHeight(rect.bottom);
int imageWidth(rect.right);
const double realMin(-2.1); // Minimum real value
double imaginaryMin(-1.3); // Minimum imaginary value
double imaginaryMax(+1.3); // Maximum imaginary value
// Set maximum imaginary so axes are the same scale
double realMax(realMin+(imaginaryMax-imaginaryMin)*imageWidth/imageHeight);
// Get scale factors to convert pixel coordinates
double realScale((realMax-realMin)/(imageWidth-1));
double imaginaryScale((imaginaryMax-imaginaryMin)/(imageHeight-1));
CClientDC hdc(this); // DC is for this view
OnPrepareDC(&hdc); // Get origin adjusted
critical_section cs; // Mutex for BitBlt() operation
parallel_for(0, imageHeight, [&](int y) // Iterate parallel over image rows
{
cs.lock(); // Lock for access to client DC
// Create bitmap for one row of pixels in image
HDC memDC = CreateCompatibleDC(hdc); // Get device context to draw pixels
HBITMAP bmp = CreateCompatibleBitmap(hdc, imageWidth, 1);
cs.unlock(); // We are done with hdc here so unlock
HGDIOBJ oldBmp = SelectObject(memDC, bmp); // Select bitmap into DC
double cReal(0.0), cImaginary(0.0); // Stores c components
double zReal(0.0), zImaginary(0.0); // Stores z components
zImaginary = cImaginary = imaginaryMax - y*imaginaryScale;
for(int x = 0; x < imageWidth; x++) // Iterate over pixels in a row
{
zReal = cReal = realMin + x*realScale;
// Set current pixel color based on n
SetPixel(memDC, x, 0, Color(IteratePoint(zReal, zImaginary, cReal, cImaginary)));
}
cs.lock(); // Lock to write to hdc
// Transfer pixel row to client area device context
BitBlt(hdc, 0, y, imageWidth, 1, memDC, 0, 0, SRCCOPY);
cs.unlock(); // Release the lock
SelectObject(memDC, oldBmp);
DeleteObject(bmp); // Delete bmp
DeleteDC(memDC); // and开发者_开发百科 our working DC
});}
The code for parallel execution is different from the serial execution code that it creates separate rows of the Mandelbrot image in parallel, and uses a critical section lock to make sure the threads don't fight over the same device context handle.
Now the reason I said there is memory leak reported sometimes is because running the release build does not cause a memory leak to be reported. Also, when running parallel execution function multiple times I don't really notice more memory being being used up, I have 6GB of RAM in case anyone is wondering. As far as the performance goes, my quad-core machine does actually present a roughly 4x increase in calculation+drawing speed from serial execution. I've also seen similar questions asks on the msdn website, but not of much use, because this may be a VS bug. Anyway, I'd like a parallel programmer's opinion.
This problem is documented in the fix-list for VS2010 SP1. The feedback article is here. Beware that SP1 is still in beta right now so avoid installing it on important production machines. Download is here.
What I would say is, write a quick deleter function for unique_ptr and use that for your resources. The only way I could see this code leaking is by throwing, but I don't see any places that throw. Once you remove that vulnerability, I don't see any leaks at all.
You have mentioned that the leak occurs 'some times' and not always. However, there is no branching in your code (specifically: branching with memory allocations) so either it should always cause the leak or never cause the leak. Moreover, as already mentioned in my comment, Memory is being allocated only at two place for memDc and bmp
and you are properly cleaning up the resources for both the variables.
In simple words, I want to say that there is no leak in the above code :) If there is actually a leak in your application, that would be in some other code path probably.
精彩评论