开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜