Плохой доступ в boost :: future & lt; & gt; .then () после доступа к данному будущему

Я разрабатываю для iOS в XCode 4.6. Я пишу библиотеку для службы и использую 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 ++, я был бы рад каждой части информации о том, в чем причина, как ее отладить и как знать, если эта проблема появится в следующий раз. Также я не совсем уверен, какая информация актуальна. То, что я понял, может быть уместно из того, что я нашел там, следующее может: ResultListener а также Service являются boost::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, и кажется, что Манкарнас (в комментариях) и я (выше) правы: кажется, часть памяти, в которой хранится продолжение освобождается и, следовательно, происходит неопределенное поведение.

Это ситуация до get() называется:
Ситуация перед & lt; code & gt; get & lt; / code & gt; называется

Это ситуация после get() назывался:
Ситуация после & lt; code & gt; get & lt; / code & gt; назывался

Адрес px указывает на это 0x00 после этого.

5

Решение

Я открыл билет против повышения 1,53 и это было подтверждено как ошибка. Кажется, что future.then еще не стабилен и поэтому не готов к использованию. Один совет оттуда был использовать

#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET

Но было четко заявлено, что эта функция еще не стабильна (и что в документации не хватает этой информации).

Сейчас я переключился на использование отдельного потока, в котором я буду ждать будущего и затем выполню соответствующие действия.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]