5

XCode4.6でiOS用に開発しています。私はサービス用のライブラリを作成していて、boostを使用してスレッドを開始しています。私の方法の1つは次のようになります。

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を追加しても、その呼び出しが機能しているので、私はこれに非常に驚いています。onErrorif

C ++にまったく慣れていないので、理由、デバッグ方法、次回この問題が発生した場合の認識方法に関するすべての情報に満足しています。また、どの情報が関連しているかはよくわかりません。私が考えたものは、これまでに見つけたものと関連している可能性があります。次の可能性がResultListenerありServiceますboost::noncopyableshared_ptr(を使用して)の参照カウントを確認したuse_countところ、継続内で増加しています。私はブースト1.53を使用しています。メソッドはこのように呼び出されます

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

foostd::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です。私の推測では、これは継続がまだ実行されているメモリを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";
    }
};

XCodeで撮った2つのスクリーンショットを追加して、継続が実行されている将来の状況を示しています。Mankarnas(コメント内)と私(上記)は正しいようです。継続が保存されているメモリ部分のようです。が解放されるため、未定義の動作が発生します。

これは、以前get()は次のように呼ばれる 状況です。<code> get</code>が呼び出される前の状況

get()これは、呼び出され た後の状況です。<code> get</code>が呼び出された後の状況

pxが指すアドレスは0x00後でです。

4

1 に答える 1

2

ブースト1.53に対してチケットを開きましたが、バグとして確認されました。まだ安定してfuture.thenいないため、本番環境で使用する準備ができていないようです。そこからのアドバイスの1つは

#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET

しかし、この機能はまだ安定していない(そしてドキュメントにはこのビットの情報が不足している)と明確に述べられていました。

私は今、別のスレッドを使用するように切り替えました。このスレッドでは、将来を待ち、適切なアクションを実行します。

于 2013-02-18T08:06:45.633 に答える