2017-09-15 28 views
6

Aşağıdaki kod, 'un aksine, Debug modu altında MSVC ile oluşturulduğunda rasgele aralıklarla çöküyor.std :: future'e MSVC'nin Debug modu altında atanırken kilitlenme

#include <future> 

using namespace std; 

int main() { 
    auto l = [](){}; 
    auto f = async(launch::async, l); 

    for (int i = 0; i < 1000000; ++i) 
     f = async(launch::async, l); 
} 

çıkış konsolu söyler:

f \ dd \ vctools \ crt \ crtw32 \ stdcpp \ thr \ mutex.c (51): muteksin tahrip ederken yoğun

Tüm çağrı yığını: https://pastebin.com/0g2ZF5C1

Şimdi açıkçası sadece bir stres testi, ama tamamen aptalca bir şey yapıyorum?

Bültenleri paylaşılan durum ve * Bu

diğer içeriğini taşımak-atar: O operator= söylenir gibi, varolan geleceğe yeni bir görev yeniden atamak için gayet Bana öyle geliyor (http://en.cppreference.com/w/cpp/thread/future/operator%3D'dan dolayı).

MSVC'nin çalışma zamanında bir hata mı?

for (int i = 0; i < 1000000; ++i) { 
    f.wait(); 
    f = async(launch::async, l); 
} 

değil operator= mı kendisi wait araması gerekiyordu:

Dikkat çekici, elle böylece içine döngü haline atama öncesi bekleme() ararsanız programı kilitleniyor durdurur?

Geçmiş:

_MSC_VER1911

Kodu yardımıyla inşa edilmiş eşittir:

Microsoft Visual Studio Community 2017 Preview(2) 
Version 15.4.0 Preview 2.0 

Sadece yepyeni C++ proje açtı.

+0

msvc ve derleyici tam sürümü yararlı olacaktır. – Yakk

+0

Sadece bir tahminde bulunun: Muhtemelen f'yi yeniden denemeye çalışırken muhtemelen 'l' devam ediyor.Muhtemelen, hata ayıklamada lambda oluşturma yükü, kalan kodun hata ayıklama sürümüne göre çok daha büyüktür. Bu sadece hata ayıklama sürümünde olduğunu açıklayabilir. –

+0

@Yakk Tabii, soruyu düzenledim. –

cevap

1

'un kendisi wait'u aramıyor?

Ben hiç sözde olup olmadığını bilmiyorum, ama <future> ait MSVC15.3.4 uygulama kısmına üstün körü kuvvetle öyle değil önermek gibi görünüyor. wait arayarak olarak gören

//User Code 
future f = /*...*/; 
f = /*...*/; //(1) 
//MSVC Code 
future& operator=(future&& _Right) _NOEXCEPT //(1) 
    { // assign from rvalue future object 
    _Mybase::operator=(_STD move(_Right)); //(2) 
    return (*this); 
    } 
_State_manager& operator=(_State_manager&& _Other) //(2) 
    { // assign from rvalue _Other 
    _Move_from(_Other); //(3) 
    return (*this); 
    } 
void _Move_from(_State_manager& _Other) //(3) 
    { // move stored associated asynchronous state object from _Other 
    if (this != _STD addressof(_Other)) 
     { // different, move 
     if (_Assoc_state) 
      _Assoc_state->_Release(); //(4) 
     _Assoc_state = _Other._Assoc_state; 
     _Other._Assoc_state = 0; 
     _Get_only_once = _Other._Get_only_once; 
     } 
    } 
void _Release() //(4) 
    { // decrement reference count and destroy when zero 
    if (_MT_DECR(_Refs) == 0) 
     _Delete_this(); //(5) 
    } 
void _Delete_this() //(5) 
    { // delete this object 
    if (_Deleter) 
     _Deleter->_Delete(this); //External Code 
    else 
     delete this; 
    } 

o wait ifadeyi dahil etmek daha iyi olabilir, şeyleri senkronize etmek ve future nesne değiştirilecek güvenli bir durumda olduğunu sağlamaya yardımcı olur.