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

时间:2013-02-12 10:03:11

标签: c++ boost ios6 exc-bad-access boost-thread

我正在为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;
    });
}

在设备上执行此操作时,我会在标记的行处获得EXC_BAD_ACCESS。我对此感到非常惊讶,因为第一次拨打onConnected是成功的,即使我在onError之前添加了if来电话也是如此。

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

Servuce reco(/* ... */);
boost::shared_ptr<foo> f(new foo());
reco.start(f);

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

我认为这是问题所在。对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";
    }
};

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

这是调用get()之前的情况: Situation before <code>get</code> is called

调用get()后的情况如下: Situation after <code>get</code> was called

之后地址px指向0x00

1 个答案:

答案 0 :(得分:2)

我打开了一张针对提升1.53 and it was confirmed的罚单作为错误。似乎future.then尚未稳定,因此尚未准备好用于生产。一个建议是使用

#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET

但有人明确表示此功能尚不稳定(并且文档缺少这些信息)。

我现在已经切换到使用一个单独的线程,我将等待未来并执行适当的操作。