12

私はプログラムを試しています:

#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 x64。

建てる:

cl /EHsc /Zi async.cpp && async

私にとって、このプログラムはクラッシュします。物理的に同時に実行されるフューチャーの数には制限があるのではないかと思います。反復回数を数回に減らすと、うまくいきます。

だから、2つの質問:

  1. C++11 で実際に Future を実行することに制限はありますか?

  2. このコードがクラッシュするのはなぜですか? 「async()」の直後に明示的に「get()」を実行すると、次の反復の前にフューチャーを完了する必要があります。つまり、一度に 1 つのフューチャーのみが実行されます。

アップデート

コードを次のように簡略化しました。

#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++
async.exe!??$_ApplyX@X@?$_Callable_obj@V<lambda_A200A86DFF9A63A1>@?2???$?0V?$_Bind@$0A@XV<lambda_23AC5A2FBB53FD4D>@?5?main@U_Nil@std@@U23@U23@U23@U23@U23@U23@@std@@@?$_Async_state@H@std@@QEAA@$$QEAV?$_Bind@$0A@XV<lambda_23AC5A2FBB53FD4D>@?5?main@U_Nil@std@@U23@U23@U23@U23@U23@U23@@3@@Z@$0A@@std@@QEAAXXZ() Line 420  C++
async.exe!?_Do_call@?$_Func_impl@U?$_Callable_obj@V<lambda_A200A86DFF9A63A1>@?2???$?0V?$_Bind@$0A@XV<lambda_23AC5A2FBB53FD4D>@?5?main@U_Nil@std@@U23@U23@U23@U23@U23@U23@@std@@@?$_Async_state@H@std@@QEAA@$$QEAV?$_Bind@$0A@XV<lambda_23AC5A2FBB53FD4D>@?5?main@U_Nil@std@@U23@U23@U23@U23@U23@U23@@3@@Z@$0A@@std@@V?$allocator@V?$_Func_class@XU_Nil@std@@U12@U12@U12@U12@U12@U12@@std@@@2@XU_Nil@2@U42@U42@U42@U42@U42@U42@@std@@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を使用しています。

4

4 に答える 4

4
  1. 配列の大きさに制限があるように、明らかに実装上の制限があります。起動ポリシーが lauch::async で、システムが新しいスレッドを開始できなかった場合、std::async はエラー 'resource_unavailable_try_again' を通知できます。しかし、このエラーは発生しません。

  2. プログラムはクラッシュするべきではなく、私にとってはクラッシュしません (VS11 x64、リリース ビルド、同じソースとコマンド ライン)。

    .get()プログラムがなくても、一度に複数の非同期操作が行われることはないと思います。未来をローカル変数に割り当てると、ループの反復ごとに未来が破棄され、次のループ反復で別の操作を開始する前に非同期操作が強制的に完了します。

于 2012-04-24T18:16:33.820 に答える
1
  1. いいえ、標準はスレッド サポート ライブラリに関する制限を述べていません (スレッド、将来などを含む)。

  2. これは、スレッド サポート ライブラリの実装品質と基になる API に依存します。あなたが言うようf.get()に、タスクのコンパイルを待ちます(この動作には C++ 標準が必要です)。ライブラリの実装が、基礎となる API のスレッド ハンドルなどのリソースを再利用できない場合、システム リソースの不足やプログラムのクラッシュが発生する可能性があります。それはライブラリ実装の品質です。

于 2012-05-02T07:38:35.967 に答える
1

コードを main() に try-catch で囲み、std::exception がスローされるかどうかを確認してください。これはヒントになるかもしれません。それに加えて、VS の C++11 はまだベータ版です。

于 2012-04-29T15:28:22.967 に答える
0

std=c++11 オプションを指定して g++ を使用している場合は、最新バージョンであることと pthread にリンクしていることを確認してください。

たとえば、CodingGround では、([コンパイル] ボタンを使用して) 得られる既定のコンパイルは次のとおりです。

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

"what(): Unknown error -1"で失敗します。ただし、手動で-lpthreadをコンパイル コマンドに追加できます。

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

そしてそれはうまくいきます。

于 2017-03-17T06:43:21.740 に答える