2017-09-15 2 views
6

Der folgende Code stürzt in zufälligen Intervallen ab, wenn er mit MSVC unter Debug erstellt wird, im Gegensatz zu Release.Absturz beim Zuweisen zu std :: future unter MSVCs Debug-Modus

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

Die Konsolenausgabe sagt:

f: \ dd \ vctools \ crt \ crtw32 \ stdcpp \ thr \ mutex.c (51): Mutex zerstört, während beschäftigt

Der vollständige Callstack lautet: https://pastebin.com/0g2ZF5C1

Jetzt ist es offensichtlich nur ein Stresstest, aber mache ich etwas völlig Dummes? Es scheint mir, es ist in Ordnung, eine neue Aufgabe zu einer bestehenden Zukunft neu zuzuweisen, wie es gesagt wird, dass operator=:

Releases jeder freigegebener Zustand und die Inhalte andere bewegen-zuordnet * this

(Wegen http://en.cppreference.com/w/cpp/thread/future/operator%3D).

Ist es ein Fehler in MSVC Laufzeit?

Bemerkenswert ist, stoppt das Programm abstürzt, wenn ich() vor der Zuweisung manuell Warte aufrufen, damit die Schleife in die Herstellung:

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

Ist das nicht operator= selbst soll wait nennen?

Hintergrund:

_MSC_VER gleich 1911

Code mit Hilfe gebaut wurde:

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

gerade ein brandneues C++ Projekt.

+0

Genaue Version von msvc und Compiler wäre nützlich. – Yakk

+0

Nur eine Vermutung: Manchmal wird 'l' immer noch ausgeführt, während Sie versuchen, f neu zuzuweisen.Wahrscheinlich ist der Overhead beim Erstellen des Lambda im Debug-Modus viel größer im Vergleich zum Overhead der Debug-Version des verbleibenden Codes. Das könnte erklären, dass es nur in der Debug-Version passiert. –

+0

@Yakk Sicher, ich habe die Frage bearbeitet. –

Antwort

1

Ist nicht operator= selbst soll wait anrufen?

Ich weiß nicht, ob es sich um soll, aber ein flüchtiger Blick auf die MSVC15.3.4 Umsetzung <future> scheint stark zu deuten darauf hin, es funktioniert nicht.

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

als Aufruf sehen wait hilft, die Dinge synchronisieren und stellen Sie sicher, dass das future Objekt in einem sicheren Zustand geändert werden soll, könnte es besser sein, die wait Aussage aufzunehmen.

Verwandte Themen