2017-01-05 18 views
0

このコードではリークが発生しています。私はオブジェクトをベクトルとラムダ関数に間違って渡していることを知っていますが、その解決方法は本当にわかりません。コードのレビューと修正を私にお願いしますか?スレッド内のラムダ関数に変数を正しく渡す方法

std::vector<std::thread> threads; 
std::vector<std::unique_ptr<FileHandler>> fileHandlers; 

for (std::string argument : filesToParse) 
{ 
    std::unique_ptr<FileHandler> fileHandler(new FileHandler(argument)); 
    fileHandlers.push_back(std::move(fileHandler)); 

    threads.push_back(std::thread([&fileHandler]() 
    { 
     fileHandler->processFile(); 
    })); 
} 

for(auto i = 0; i < threads.size(); ++i) 
{ 
    threads.at(i).join(); 
    fileHandlers.at(i)->mergeMaps(finalMap); 
} 
+2

'std :: move(fileHandler)'で気をつけてください。すぐ後にアクセスしようとします。最新のファイルハンドラを取得するには、 'fileHandlers.back()'を使ってみてください。 –

+0

移動したハンドラをプッシュバックした後、 'fileHandler'は未指定の状態のままです。これはおそらくそれがもう何も指していないことを意味します。次に、ラムダを、関数の戻り値を超えて保持されているコンテナ内のスレッド内に格納します。したがって、スレッドが結合されると、ラムダ内の 'fileHandler'は、すでに移動された存在しない値へのダングリング参照です(存在したときのyoreの日であっても)。 – bipll

答えて

2

示されたロジックにはいくつかの問題があります。

fileHandlers.push_back(std::move(fileHandler)); 

ここに離れて移動されたunique_ptrをfileHandlerの内容。この直後:

threads.push_back(std::thread([&fileHandler]() { 

これは通過し、それぞれの新しいスレッドに、内容unique_ptrへの参照がちょうどから離れて移動されました。このunique_ptrはメーカーに会いに行きました。それは存在しなくなった。合唱団は見えない。それはex-unique_ptrです。

fileHandlers.push_back(std::move(fileHandler)); 

この文に戻る。 1つの価格で2つの論理エラーが発生します。

fileHandlersはベクターである。ベクトルに値を追加すると、ベクトルを再割り当てすることができます。再配置は、既存のイテレータ、ポインタ、またはベクトルの既存の内容への参照をすべて無効にします。このベクトル内の何かへの参照を渡し、その後、ベクトルが再割り当てされると、ループの次の繰り返しでこのベクトルに何かを追加します。

fileHandlersベクトルに、すべてのスレッドのすべてのパラメータのリストを入力することは、明白な目的です。

  1. 使用reserve()は何の再配分がその後発生していないことを確認する:それを正しく行うには2つの基本的な方法があります。

  2. まず、すべての値をベクトルに取り込み、すべてのスレッドを生成して、今完了したベクトル内の独自のパラメータへの参照を各スレッドに渡します。

あなたはこれらの問題を解決する方法はいくつかあります。

  1. は、第一のベクターを移入し、またはその内容を確保し、各スレッドではないfileHandler unique_ptrをに渡すが、unique_ptrへの参照配列がすでに入力されているfileHandlers配列

  2. あるいは、予約、またはshared_ptr Sに切り替えることにより、事前にベクターを移入し、キャプチャのいずれか回避することの価値各スレッドのshared_ptrパラメータによって

+0

コードの例を教えてください。私がJava環境から来たので、すべてを正しく理解しているかどうかはわかりません。 –

関連する問題