1

저는 간단한 네이티브 MFC 응용 프로그램을 만들고 있고, 동시성 네임 스페이스를 사용하여 간단한 병렬 프로그램 (Mandelbrot 집합 그리기)을 수행하고 있습니다. 이 프로그램은 지금까지 아주 기본적으로 하나의 버튼을 클릭하면 병렬로 그려지고, 다른 하나는 직렬로 그려집니다. 직렬 실행 기능은 매우 기본적이고 올바른 그림을 그립니다. 그러나 병렬 실행 기능과 마찬가지로 디버그 빌드를 실행하고 프로그램을 종료 할 때 출력에서 ​​메모리 누수가 있음을 알 수 있습니다. 여기 parallel_for 함수로 인해 메모리 누수가 발생합니다. (가끔)

코드이다 :

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 
});} 

병렬 실행을위한 코드가 병렬 만델 화상의 별도의 열을 생성하는 일련의 실행 코드와 다르고, 쓰레드 확인 크리티컬 섹션 잠금 사용 같은 장치 컨텍스트 핸들을 통해 싸우지 마십시오.

이제 메모리 누수가보고 된 이유는 릴리스 빌드를 실행해도 메모리 누수가보고되지 않기 때문입니다. 또한, 병렬 실행 기능을 여러 번 실행하면 더 많은 메모리가 소모되는 것을 실제로 인식하지 못합니다. 누군가가 궁금해하는 경우 6GB의 RAM이 있습니다. 성능면에서 볼 때, 제 쿼드 코어 머신은 실제로 직렬 실행에서 계산 + 드로잉 속도가 대략 4 배 증가했습니다. msvn 웹 사이트에서도 이와 유사한 질문을하지만 VS 버그 일 수 있기 때문에 많이 사용하지는 않습니다. 어쨌든, 필자는 병렬 프로그래머의 의견을 원합니다.

+0

누수가 예상되는 곳을 좁히려 고 시도해 보셨습니까? GDI 코드 (GDI 리소스 누출은 거의 메모리 누수로보고되지 않음)에서 비롯된 것이 아니므로 모든 것을 제거하고 IteratePoint 루프를 병렬로 호출하면됩니다. 그래도 여전히 누출되면, 무엇을하는지보십시오 (제공된 코드 샘플에서는 볼 수 없습니다). –

+0

@Leo 사실, parallel_for 함수에서 모든 것을 제거했는데, parallel_for 문을 사용하면 디버그 빌드를 실행할 때 메모리 누수가 발생하는 것 같습니다. VS10 설치시 컴파일러, 디버거 또는 작은 결함 일 수 있습니다. 나는 아직도 약간의 설명을 원할 것이다. – sj755

+1

관련없는 코드를 모두 제거하려면 질문을 편집해야합니다. 그런 식으로 사람들은 무엇이 잘못 될지를 볼 수있게 될 것입니다. 또한 단지 잘못보고 된 것이 아니라고 확신합니까? 메모리 누수 도구는 가양성에 대해 악명이 높습니다. 어느 도구가이를보고하고 있으며 정확하게보고하고 있습니까? –

답변

1

이 문제는 VS2010 SP1의 fix-list에 설명되어 있습니다. 의견 기사 is here. SP1은 아직 베타 버전이므로 중요한 프로덕션 컴퓨터에 설치하지 마십시오. is here을 다운로드하십시오.

+0

감사합니다. 훨씬 구체적인 답변입니다. 그러나 Windows Vista 사용에 대한 나의 추억은 완전히 준비되지 않은 소프트웨어 사용에 신경을 곤두 세우므로 베타 버전을 다운로드하는 대신 Windows Update를 설치할 때까지 기다릴 것입니다. 다시 한번 감사드립니다. – sj755

0

당신은 누수가 항상 발생한다고 언급 한 적이 있습니다. 그러나 코드에는 분기가 없으므로 (특히 메모리 할당으로 분기) 누수가 발생하거나 누수가 발생하지 않아야합니다. 또한, 내 의견에 이미 언급 한 바와 같이, 메모리는 memDc and bmp에 대해 두 곳에서만 할당되고 있으며 두 변수에 대한 리소스를 올바르게 정리하고 있습니다.

간단히 말해 위 코드에서 누출이 없다고 말하고 싶습니다. 실제로 응용 프로그램에 누수가있는 경우 다른 코드 경로에있을 가능성이 큽니다.

+0

@ Vikram.exe 이전 코멘트에 대답하기 위해 필자는 모든 객체를 제거하고 parallel_for 루프에서 메모리 누수가보고되지만 paralel_for 함수를 완전히 제거해도 메모리 누수가보고되지 않습니다. 실제로 응용 프로그램에서 누수가 무슨 뜻인지 확실하지 않습니다. 응용 프로그램에는 함수를 실행하는 것 이상을 수행하는 두 개의 단추가 추가 된 기본 MFC보기 만 있습니다. 당신은 정교 할 수 있습니까? – sj755

+0

paralel_for 함수를 제거한 후 누수가보고되지 않으면 안전하게 내 주석을 무시할 수 있습니다 :). 그러나 나는 아직도 여기에 누수가 있다고 생각하지 않는다. –

+0

@ Vikram.exe 귀하의 의견으로는, 그것은 단지 거짓 긍정적입니까? – sj755

1

내가 말하는 것은 unique_ptr에 대한 빠른 삭제 기능을 작성하고 리소스에 사용하는 것입니다. 이 코드가 누출되는 것을 볼 수있는 유일한 방법은 던지기 만하지만 던지는 곳은 없습니다. 이 취약점을 제거하면 누출이 전혀 보이지 않습니다.

관련 문제