2017-09-15 13 views
6

के तहत std :: भविष्य को असाइन करते समय क्रैश Release के विपरीत Debug मोड के तहत MSVC के साथ बनाया गया यादृच्छिक अंतराल में निम्न कोड क्रैश हो जाता है।एमएसवीसी के डीबग मोड

#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); 
} 

सांत्वना उत्पादन का कहना है:

च: \ dd \ vctools \ CRT \ crtw32 \ stdcpp \ thr \ mutex.c (51): म्युटेक्स नष्ट जबकि व्यस्त

पूर्ण कॉल स्टैक है: https://pastebin.com/0g2ZF5C1

अब स्पष्ट रूप से यह केवल एक तनाव परीक्षण है, लेकिन क्या मैं कुछ बेवकूफ कर रहा हूं? मुझे ऐसा लगता है यह एक मौजूदा भविष्य के लिए एक नया कार्य पुन: असाइन करने ठीक है, के रूप में यह कहा जाता है कि operator=:

विज्ञप्ति किसी भी साझा राज्य और * इस

करने के लिए अन्य की सामग्री को ले जाने-प्रदान करती है (http://en.cppreference.com/w/cpp/thread/future/operator%3D के कारण)।

क्या यह एमएसवीसी के रनटाइम में एक बग है?

उल्लेखनीय है, कार्यक्रम अगर मैं मैन्युअल रूप से काम करने से पहले प्रतीक्षा() कहते हैं, इस प्रकार में पाश बनाने दुर्घटनाग्रस्त बंद हो जाता है:

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

नहीं operator= है ही wait कॉल करने के लिए माना जाता?

पृष्ठभूमि:

_MSC_VER के बराबर होती है 1911

कोड की मदद से बनाया गया था:

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

बस एक नया सी ++ परियोजना खोला।

+0

एमएसवीसी और कंपाइलर का सटीक संस्करण उपयोगी होगा। – Yakk

+0

बस एक अनुमान: कभी-कभी संभवतः 'एल' अभी भी निष्पादित किया जाता है जब आप f को पुन: असाइन करने का प्रयास करते हैं।शायद डीबग में लैम्ब्डा बनाने का ओवरहेड शेष कोड के डीबग संस्करण के ओवरहेड की तुलना में काफी बड़ा है। यह समझा सकता है कि यह केवल डीबग संस्करण में होता है। –

+0

@Yakk निश्चित रूप से, मैंने सवाल संपादित किया है। –

उत्तर

1

operator=wait पर कॉल करने वाला नहीं है?

मैं क्या यह करने के लिए चाहिए है पता नहीं है, लेकिन <future> की MSVC15.3.4 कार्यान्वयन पर एक सरसरी नज़र दृढ़ता से सुझाव के लिए यह नहीं है लगता है।

//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; 
    } 

wait बुला के रूप में देखकर बातें सिंक्रनाइज़ और सुनिश्चित करें कि future वस्तु एक सुरक्षित स्थिति में है संशोधित करने की है, यह बेहतर हो सकता है wait बयान शामिल करने के लिए मदद करता है।