1

私は単純なネイティブMFCアプリケーションを作成していますが、シンプルな並列プログラム(Mandelbrotセットを描画)を実行するためにConcurrency名前空間を使用しています。プログラムはこれまでのところ非常に基本的なものであり、一方のボタンをクリックすると並行して描画され、もう一方のボタンは並行して描画されます。シリアル実行機能は非常に基本的で、正しい画像を描画します。しかし、並列実行機能と同様に、デバッグビルドを実行してプログラムを終了すると、出力はメモリリークがあることを示します。ここで 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倍の増加を示します。 私は同様の質問がmsdnウェブサイトで尋ねてきましたが、これは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の2つの場所でのみ割り当てられており、両方の変数のリソースを適切にクリーンアップしています。

簡単な言葉で言えば、私は上記のコードに漏れがないと言いたいと思っています:) 実際にあなたのアプリケーションにリークがある場合、おそらく他のコードパスになります。

+0

@ Vikram.exeあなたの以前のコメントに答えるために、文字通りすべてのオブジェクトを削除し、parallel_forループからメモリリークが報告されていましたが、paralel_for関数を完全に削除してもメモリリークは報告されません。私は実際にあなたがアプリケーションのリークによって何を意味するかはわかりません。アプリケーションには、関数を実行する以外の何もしない2つのボタンが追加された基本的なMFCビューしかありません。あなたは詳しく説明できますか? – sj755

+0

paralel_for関数を削除してもリークが報告されない場合は、私のコメントを無視してもかまいません:)。しかし、私はまだここに漏れがあるとは思わない。 –

+0

@ Vikram.exeあなたの意見では、それは単に偽陽性ですか? – sj755

1

私が言うことは、unique_ptrのクイック・デリター関数を作成し、それをあなたのリソースに使用することです。私はこのコードが漏れるのを見ることができる唯一の方法は投げることですが、スローする場所はありません。この脆弱性を削除すると、漏れはまったくありません。

関連する問題