访问给定的未来后,在boost :: future <>.then()中访问不良

Ste*_*han 5 c++ boost exc-bad-access boost-thread ios6

我正在为XCode 4.6中的iOS开发.我正在为服务编写一个库,并使用boost来启动线程.我的一个方法看起来像这样:

void Service::start(boost::shared_ptr<ResultListener> listener) {

    boost::future<bool> con = boost::make_future(true);
    listener->onConnected(); // Works
    boost::future<bool> initDone = con.then([&, listener](boost::future<bool>& connected) {
         listener->onConnected(); // Works
         if (!connected.get()) {
             listener->onError("...");
             return false;
         }
         listener->onError("...");  // EXC_BAD_ACCESS
         /* ... */
         return true;
    });
}
Run Code Online (Sandbox Code Playgroud)

在设备上执行此操作时,我会EXC_BAD_ACCESS在标记的行处获得.我对此感到非常惊讶,因为第一次调用onConnected是成功的,即使我在该onError调用之前添加了一个调用if也是有效的.

由于对C++缺乏经验,我会对每一条信息感到高兴,这些信息是关于什么原因,如何调试它以及如何在下次发生此问题时如何发现.此外,我不太确定哪些信息是相关的.我所知道的可能与我迄今为止所发现的相关,以下可能是:ResultListener并且Serviceboost::noncopyable.我检查了shared_ptr(使用use_count)的引用计数,它在继续中增加.我正在使用boost 1.53.这个方法就是这样调用的

Servuce reco(/* ... */);
boost::shared_ptr<foo> f(new foo());
reco.start(f);
Run Code Online (Sandbox Code Playgroud)

foo是一个简单的类,std::cout如果调用一个方法,它只会打印.

编辑:进一步窥探让我检查get()调用,我发现以下代码future.hpp正在执行:

    // retrieving the value
    move_dest_type get()
    {
        if(!this->future_)
        {
            boost::throw_exception(future_uninitialized());
        }

        future_ptr fut_=this->future_;
        this->future_.reset();
        return fut_->get();
    }
Run Code Online (Sandbox Code Playgroud)

我认为这是问题所在.呼吁reset()似乎释放了记忆future_ shared_ptr.我的猜测是,这标志着listener延迟仍在运行的内存,因为没有用于操作系统,因此使指针无效,然后指示内存访问超出其范围.这个假设是否正确?我可以以某种方式避免这种情况,或者这是一个提升中的错误?

编辑2:以下是创建问题的最小示例:

#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>

class Test {

public:
    void test() {
        boost::shared_ptr<Test> listener(new Test());
        boost::future<bool> con = boost::make_future(true);
        listener->foo(); // Works
        boost::future<bool> initDone = con.then([listener](boost::future<bool>& connected) {
            listener->foo(); // Works
            if (!connected.get()) {
                listener->foo();
                return false;
            }
            listener->foo();  // EXC_BAD_ACCESS
            return true;
        });
    }

    void foo() {
        std::cout << "foo";
    }
};
Run Code Online (Sandbox Code Playgroud)

我在XCode中添加了两个截图,以显示将来运行conitnuation的情况,看起来Mankarnas(在评论中)和我(上面)是正确的:似乎是存储延续的内存部分被释放,因此发生未定义的行为.

这就是之前的情况get(): 调用<code>get()</code>被称为后的情况: 
<img rel=

Ste*_*han 2

我针对 boost 1.53 开了一张票,并被确认为一个错误。似乎future.then还不稳定,因此尚未准备好用于生产使用。那里的一个建议是使用

#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
Run Code Online (Sandbox Code Playgroud)

但明确指出该功能尚未稳定(并且文档缺乏这方面的信息)。

我现在已切换为使用单独的线程,在该线程中我将等待未来并执行正确的操作。