2015-02-08 35 views
1

考慮以下針對boost v1.53構建的程序。我期望z = 10作爲輸出,但程序打印z = -1294967296。有人可以解釋爲什麼嗎?任何人都可以解釋這個來自boost :: thread的意外結果嗎?

// g++ -std=c++11 -O2 -Wall -pedantic -lboost_system -lboost_thread main.cpp && ./a.out 
#include <iostream> 
#include <iomanip> 
#include <boost/thread.hpp> // boost v1.53 

struct S { 
    boost::packaged_task<void> task; 
    boost::thread th; 
    void async_start(int z) { 
     auto worker = [=]() { 
      boost::this_thread::sleep_for(boost::chrono::seconds{1}); 
      std::cout << "z = " << z << '\n' << std::flush; // does not z have the same value as the async_start arg? 
     }; 
     task = boost::packaged_task<void>{worker}; // is not 'worker' copied? 
     th = boost::thread{std::move(task)}; // start 
    } 
}; 

int main() { 
    S s; 
    s.async_start(10); 
    boost::this_thread::sleep_for(boost::chrono::seconds{3}); // wait some time to make the thread finish 
    s.th.join(); 
} 

// z = -1294967296 
+0

我無法複製此內容。它爲我輸出10,Valgrind不報告任何無效的內存訪問。 – 5gon12eder 2015-02-08 22:40:24

+1

編譯命令對我不起作用,應在鏈接器參數前提供'main.cpp'。我的系統用boost 1.56和g ++ 4.9打印10。你可能想嘗試定義'BOOST_THREAD_VERSION = x'。它包含或排除的某些代碼取決於您使用的版本。最近的是4. – en4bz 2015-02-08 22:42:01

+0

我不能在coliru上重現它,但是我可以在使用boost v1.53的時候使用它。它可能是boost v1.53中的一個bug嗎? – Martin 2015-02-08 22:42:03

回答

3

這似乎是升壓bug 8596,固定在升壓1.54。

簡而言之,在C++ 11模式下,boost::packaged_task的構造函數在傳遞一個左值時存儲引用(!)而不是副本時被破壞。仿函數是通過轉發引用獲取的,這意味着當左值被傳遞時,模板參數被推斷爲左值引用。代碼顯然忽略了剝奪參考性。

作爲確認,傳遞一個prvalue到packaged_task的構造(通過直接使用lambda表達式)fixes the problem:通過使用std::move(worker)

task = boost::packaged_task<void>{[=]() { 
     boost::this_thread::sleep_for(boost::chrono::seconds{1}); 
     std::cout << "z = " << z << '\n' << std::flush; 
    }}; 

so does passing an xvalue

相關問題