2012-04-24 41 views
12

我想一個程序編號異步/期貨:在C++ 11

#include <iostream> 
#include <thread> 
#include <future> 

int foo() { 
    return 0; 
} 

int main(int argc, char* argv[]) { 
    for (auto i = 0L; i < 10000; ++i) { 
    auto f = std::async(foo); 
    f.get(); 
    } 
    return 0; 
} 

編譯VS11 64。

體形:

cl /EHsc /Zi async.cpp && async 

對於我這個程序崩潰。我懷疑,同時實際運行的期貨數量是有限的。如果我將迭代次數減少到幾個訂單,它就可以工作。

於是,兩個問題:

  1. 是否有實際運行期貨在C++ 11的限制?

  2. 爲什麼此代碼會崩潰?如果我明確地在「async()」之後立即執行「get()」,它必須在下一次迭代之前完成未來,這意味着一次只能運行一個未來。

UPDATE

我已經簡化了代碼:

#include <future> 

int main(int argc, char* argv[]) { 
    for (auto i = 0L; i < 1000000; ++i) { 
    auto f = std::async([](){ return 0; }); 
    f.get(); 
    } 
    return 0; 
} 

它仍然崩潰了我。它不扔,我檢查了。但現在我有一個可見的堆棧跟蹤:

async.exe!_Mtx_unlock(_Mtx_internal_imp_t * * mtx) Line 229 C++ 
async.exe!std::_Mtx_unlockX(_Mtx_internal_imp_t * * _Mtx) Line 84 C++ 
async.exe!std::_Mutex_base::unlock() Line 47 C++ 
async.exe!std::unique_lock<std::mutex>::~unique_lock<std::mutex>() Line 284 C++ 
async.exe!std::_Associated_state<int>::_Set_value(int && _Val, bool _At_thread_exit) Line 358 C++ 
async.exe!std::_Packaged_state<int __cdecl(void)>::_Call_immediate() Line 569 C++ 
async.exe!std::_Async_state<int>::`std::U_Nil::ain::ain'::`3'::<lambda_A200A86DFF9A63A1>::operator()() Line 700 C++ 
[email protected]@[email protected]<lambda_A200A86DFF9A63A1>@[email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected][email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@QEAAXXZ() Line 420 C++ 
[email protected][email protected][email protected]<lambda_A200A86DFF9A63A1>@[email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected][email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@[email protected][email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@UEAAXXZ() Line 217 C++ 
async.exe!std::_Func_class<void,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 486 C++ 
async.exe!`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>::operator()() Line 1056 C++ 
async.exe!std::_Callable_obj<`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>,0>::_ApplyX<Concurrency::details::_Unit_type>() Line 420 C++ 
async.exe!std::_Func_impl<std::_Callable_obj<`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>,0>,std::allocator<std::_Func_class<Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> >,Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Do_call() Line 217 C++ 
async.exe!std::_Func_class<Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 486 C++ 
async.exe!`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B>::operator()() Line 325 C++ 
async.exe!Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> >::operator()() Line 72 C++ 
async.exe!Concurrency::details::_UnrealizedChore::_InvokeBridge<Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> > >(Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> > * _PChore) Line 4190 C++ 
async.exe!Concurrency::details::_UnrealizedChore::_UnstructuredChoreWrapper(Concurrency::details::_UnrealizedChore * pChore) Line 275 C++ 
async.exe!Concurrency::details::_PPLTaskChore::_DeletingChoreWrapper(Concurrency::details::_UnrealizedChore * pChore) Line 78 C++ 
async.exe!Concurrency::details::InternalContextBase::ExecuteChoreInline(Concurrency::details::WorkItem * pWork) Line 1600 C++ 
async.exe!Concurrency::details::InternalContextBase::Dispatch(Concurrency::DispatchState * pDispatchState) Line 1704 C++ 
async.exe!Concurrency::details::FreeThreadProxy::Dispatch() Line 191 C++ 
async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain(void * lpParameter) Line 173 C++ 
kernel32.dll!0000000076df652d() Unknown 
ntdll.dll!0000000076f2c521() Unknown 

和線程:

Unflagged  1864 0 Worker Thread ntdll.dll thread ntdll.dll!0000000076f518ca Normal 
Unflagged  10964 0 Main Thread Main Thread async.exe!do_signal Normal 
Unflagged  7436 0 Worker Thread ntdll.dll thread ntdll.dll!0000000076f52c1a Normal 
Unflagged  10232 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::ThreadProxy::SuspendExecution Normal 
Unflagged > 10624 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!_Mtx_unlock Normal 
Unflagged  4756 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::ThreadProxy::SuspendExecution Normal 
Unflagged  11100 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::InternalContextBase::WaitForWork Normal 
Unflagged  6440 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!std::vector<std::pair<void (__cdecl*)(void * __ptr64),void * __ptr64>,std::allocator<std::pair<void (__cdecl*)(void * __ptr64),void * __ptr64> > >::_Tidy Normal 

我使用VS 11.0.40825.2 PREREL。

+3

聽起來像一個編譯器錯誤。 – 2012-04-24 15:56:17

+0

我不相信這個調用會啓動另一個線程,它只是一個延遲執行。例如,foo應該在執行f.get()行時被調用。 – alanxz 2012-04-24 16:02:08

+1

調試器應該可以幫助您理解代碼崩潰的原因。我會在假設編譯器被破壞之前嘗試。 – 2012-04-24 16:03:10

回答

4
  1. 顯然存在實施限制,就像數組的大小有限制一樣。如果啓動策略是lauch :: async並且系統無法啓動新線程,則std :: async可以發出錯誤'resource_unavailable_try_again'。但是你沒有得到這個錯誤。

  2. 程序不應該崩潰,不適合我(VS11 64,發佈版本,相同的源和命令行)。

    我相信,即使沒有.get()程序不會有一個以上的異步操作會馬上。將未來分配給局部變量,將在每次循環迭代中銷燬未來,迫使異步操作在下次循環迭代中啓動另一個循環之前完成。

1

嘗試用try-catch將你的代碼放在main()中,並檢查它是否拋出std :: exception。這可能會提示。除此之外,VS中的C++ 11仍然是測試版。

+6

而測試版是錯誤報告最有價值的。 – 2012-04-29 15:37:00

1
  1. 不,標準沒有對線程支持庫(包括線程,未來等)的限制。

  2. 這取決於線程支持庫的實施質量和底層API。正如你所說的f.get()等待任務壓縮(此行爲需要C++標準)。當庫實現不能重用像底層API的線程句柄這樣的資源時,它可能會導致缺乏系統資源和程序崩潰。這是圖書館實施的質量。

0

如果您使用g ++與std = C++ 11選項,請確保您有最新版本並鏈接到pthread。

例如,在CodingGround,你得到(與編譯按鈕),默認的編譯是:

g++ -std=c++11 -o main *.cpp 

和它失敗「是什麼():未知錯誤-1」。但是,您可以手動添加-lpthread到編輯命令:

g++ -std=c++11 -o main -lpthread *.cpp 

,它會工作得很好。