2016-04-07 2 views
1

私は自分のファンクタにHttpRequestオブジェクト(Cocos2d-xから)をラップしようとしています。私のファンクタに渡されたコールバックを呼び出す以外はすべて正常に動作しています。あなたは下のクラスでエラーを見つけられますか? (私はコードの関連部分のみを貼り付けた)。Functorを使用したコールバックパターン

Cloud.hpp:

#ifndef Cloud_hpp 
#define Cloud_hpp 

#include "external/json/document.h" 
#include "network/HttpClient.h" 

using namespace cocos2d::network; 

typedef std::function<void()> CloudCallback; 

class Cloud 
{ 
private: 
    std::string url { "http://localhost:3000/1.0/" }; 
    std::string end_point; 
    CloudCallback callback; 

    std::string getPath(); 
    void onHttpRequestCompleted(HttpClient *sender, HttpResponse *response); 
public: 
    Cloud (std::string end_point) : end_point(end_point) {} 
    void operator() (CloudCallback callback); 
}; 


#endif /* Cloud_hpp */ 

これは、コンストラクタに渡されたコールバックを格納するクラスです。ここでは実装だ:私は何をしようとしている

#include "Cloud.hpp" 
#include <iostream> 

std::string Cloud::getPath() 
{ 
    return url + end_point; 
} 

void Cloud::operator()(CloudCallback callback) 
{ 
    this->callback = callback; 

    std::vector<std::string> headers; 

    HttpRequest* request = new (std::nothrow) HttpRequest(); 
    request->setUrl(this->getPath().c_str()); 
    request->setRequestType(HttpRequest::Type::GET); 
    request->setHeaders(headers); 
    request->setResponseCallback(CC_CALLBACK_2(Cloud::onHttpRequestCompleted, this)); 
    HttpClient::getInstance()->send(request); 
    request->release(); 
} 

void Cloud::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response) 
{ 
    this->callback(); 
} 

は次のように呼び出し、ファンクタの助けを借りて、簡単なHTTPリクエストを行い、次のとおりです。

Cloud cloud("decks"); 
cloud([&]() { 
    CCLOG("Got the decks"); 
}); 

私はEXC_BAD_ACCESS(コードを取得しています= EXC_I386_GPFLT)

this->callback(); 

と呼ばれます。

私はここで間違っていますか?

編集:今はスレッドと関係があると思います。 HttpRequestを削除してすぐにoperator()に渡されるコールバックメソッドを呼び出すと、問題なく動作します。

+0

あなたのラムダキャプチャが参考になっていることに気付いています。つまり、ローカルスコープのものの参照に掛かることになります。コールバックが呼び出された時点でそれらが破棄されると、問題が発生します。また、ローカルの 'Cloud'オブジェクトを持っています - それはhttp要求よりも寿命が長くなっていますか?コールバックが呼び出される前にクラウドオブジェクトが破棄されるため、同じことが起こります。 –

+0

httprequestが完了したら、Cloudオブジェクトが破棄されたと思います。メモリ管理はC++では難しい。 –

+0

@AlexanderKondratskiyあなたは正しいです。スコープを変更すると問題が解決しました。あなたが答えとしてあなたのコメントを投稿できるなら、私はそれを受け入れることができます。 –

答えて

0

は一生の問題である可能性があります。 http応答コールバックは非同期に呼び出されるため、その間に一部のオブジェクトが破棄されている可能性があります。 2つの可能性があります。

  • Cloudオブジェクト自体は、コールバックが呼び出される前に破棄されます。
  • ラムダが参照する1つ以上のオブジェクト(参照によってキャプチャしているため)も、範囲外になり破棄されている可能性があります。
0

:-)助けのために物乞いことは、これを試してみてください。それが問題のように見える

void Cloud::operator()(const CloudCallback &callback) 
+0

"function"というファイルのどこかで、 "return(* __ f _)(_ VSTD :: forward <_ArgTypes>(__arg)...);"という同じエラーが発生しました。 –

関連する問題