Xcode 4.6でiOS用に開発しています。私はサービス用のライブラリを作成しており、スレッドを起動するために使用します。私の方法の一つは、次のようになります。与えられた未来にアクセスした後、boost :: future <>。then()にアクセスできない
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
を使って)の参照カウントをチェックし、それは継続の中で増加します。私はブースト1.53を使用しています。この方法は、メソッドが呼び出された場合std::cout
に何もなく、プリントしません単純なクラスであること、この
Servuce reco(/* ... */);
boost::shared_ptr<foo> f(new foo());
reco.start(f);
foo
のように呼ばれています。
編集:がさらに周りスヌーピング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
のメモリを解放しているようです。私の推測では、これは、継続がOSで使用されていないとして実行されているメモリをマークして、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";
}
};
私はconitnuationが実行されている将来の状況を示すために、Xcodeで取って、それはそう2枚のスクリーンショットを追加しましたMankarnas(コメント内)と私(上)は正しいです:継続が保存されているメモリ部分が解放されているため、未定義の動作が発生するようです。
このget()
前に状況が呼び出されている:
これはget()
が呼び出された後の状況です:
アドレスpx
ポイントその後0x00
であるために。
'onError'をチェックしましたか? – inf
どういう意味ですか?それには間違ったコードが含まれていますか?これは 'std :: cout <<" foo ";'で構成され、将来の 'get()'呼び出しの前に 'onError'を呼び出すと動作します。 – Stephan
クラッシュする行の前に 'listener.get()'はnullではありませんか? (私は問題をローカルに再現することはできません;あなたが問題を示す_complete_テストケースを作成できれば、おそらくあなたが記述していない部分について推測する必要はありません)。 – Mankarse