2017-10-02 8 views
1

私はパラメータとして関数ポインタとミリ秒単位の時間をとるタイマを実装しようとしています。時間が経過した後、別のスレッドで関数を呼び出す必要があります。コードは次のようになります。C++スタック変数が壊れています

class timer 
{ 
public: 
    void schedule(void(*function)(), int time) 
    { 
     std::thread t = std::thread([&] 
      { 
       std::this_thread::sleep_for(std::chrono::milliseconds(time)); 
       function(); 
      }); 
     t.detach(); 
    } 
}; 

次のようにmainメソッドが見えます:

#define LOG(x) std::cout << x << std::endl; 


timer t1; 
timer t2; 
timer t3; 
t1.schedule([] {LOG("t1 done")}, 2000); 
t2.schedule([] {LOG("t2 done")}, 3000); 
t3.schedule([] {LOG("t3 done")}, 4000); 
std::this_thread::sleep_for(std::chrono::seconds(20)); 

次のように例外がある:

Run-Time Check Failure #2 - Stack around the variable 't1' was corrupted. 
+5

私が見ることができる唯一の問題は、ラムダを参照してキャプチャすることです。それは、スレッドがスレッドで使用される前に、スコープから外れる「時間」を与えます。値で取り込み、何が起こるか見てみてください。 '[&] - > [=]'です。 – NathanOliver

+0

返信いただきありがとうございますNathanOliver。これは問題を解決しました:) –

+0

問題はありません。私はあなたのためのより詳細な答えを書いた。 – NathanOliver

答えて

2

ここでの問題は、あなたが参照によってキャプチャされていますあなたのラムダ。これは、ラムダのoperator()が呼び出される前にdetachに電話し、scheduleから終了することが可能であることを意味します。その場合、timeを使用しようとすると、手間のかかる参照にアクセスしています。

ここでの解決方法は、代わりに値で取り込むことです。これは、コピーを取得することを意味し、ラムダが何にも依存しないため、operator()が呼び出されたときは問題ありません。

関連する問題