代码之家  ›  专栏  ›  技术社区  ›  Pythagoras of Samos

在MSVC的调试模式下分配给std::future时崩溃

  •  6
  • Pythagoras of Samos  · 技术社区  · 7 年前

    Debug 模式,不同于 Release .

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

    控制台输出显示:

    完整的调用堆栈是: https://pastebin.com/0g2ZF5C1

    operator= :

    释放任何共享状态并移动将其他的内容分配给 *这个

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

    值得注意的是,如果我在赋值之前手动调用wait(),程序就会停止崩溃,从而使循环进入:

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

    操作员= 自己应该打电话 wait

    背景:

    _MSC_VER 等于 1911

    代码是在以下帮助下生成的:

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

    刚刚打开了一个全新的C++项目。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Xirema    7 年前

    不是吗 operator= 自己应该打电话 wait

    我不知道是不是 想象上的 到,只是粗略地看一下MSVC15.3.4的实现 <future> 似乎强烈建议不要这样做。

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

    视为呼叫 帮助同步事物并确保 future 对象处于要修改的安全状态,最好包括 等待 陈述

        2
  •  0
  •   galsh83    5 年前

    我之所以要问这个问题,是因为我在MSVC调试模式中遇到了一个非常类似的问题,在 mutex destroyed while busy 消息

    here ).

    更新到VS2019为我解决了这个问题。虽然这个问题很老了,但我还是把它写下来作为另一个备选答案。