2014-04-04 23 views
0

從JS我所說的C++ - 功能是這樣的:V8 - 碰撞在HeapObject :: GetHeap() - 未初始化值

var req = new IO.HttpRequest(IO.RequestType.get); 
req.data({ i: 'jTKvNf9w' }).send('http://pastebin.com/raw.php', function (content) { console.log(content); }); 

的請求被異步地處理,並且一旦完成其回調被調用。在C++中的發送功能看起來像這樣:

void XmlHttpRequest::open(const Utils::String& str, ::JS::FunctionObjPtr callback) { 
    mCallback = callback; 
    mRequest->open(str); 
} 

後來如果請求被完成:

void XmlHttpRequest::onComplete(Utils::String content) { 
    sUIMgr->getDispatcher()->pushFrame(Gl::Dispatcher::Priority::Low, [this, content]() { 
     ::JS::FunctionObjPtr f = mCallback; 
     f->callVoid(content); 
    }); 
} 

推框架放功能在隊列在主線程中執行,其中所有腳本被設置。

現在問題出在callVoid當HeapObject :: GetHeap()調用MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();時,出現訪問衝突。這些是v8功能。問題是,this-HeapObject中的指針是0xCCCCCCCC,這意味着它是一個未初始化的值。 this -Pointer來自存儲在JS :: FunctionObjPtr(std :: shared_ptr的typedef)中的句柄。

起初我以爲我的FunctionObj有什麼問題。我通過以下方式獲得:

template<typename T> 
static TYPE_RET(FunctionObjPtr) ObjectWrap::unwrap(v8::Handle<v8::Value>& value) { 
    if (value->IsFunction() == false) { 
     TYPE_ERR("Value is not a function"); 
    } 

    return std::make_shared<FunctionObj>(value); 
} 

TYPE_RET只是在做一些模板元編程的東西。該FunctionObj看起來是這樣的:

class FunctionObj 
{ 
    v8::Handle<v8::Value> mHandle; 

public: 
    FunctionObj(v8::Handle<v8::Value>& fun) { 
     mHandle = fun; 
    } 

    FunctionObj() { } 

    operator bool() { 
     return mHandle.IsEmpty() == false; 
    } 

    template<typename... Args> 
    void callVoid(const Args&... args) { 
     std::vector<v8::Handle<v8::Value>> arguments; 
     addArgument(arguments, args...); 

     v8::TryCatch tc; 
     v8::Handle<v8::Function>::Cast(mHandle)->Call(mHandle, arguments.size(), arguments.data()); 
     if (tc.HasCaught()) { 
      throw JS::Exception(tc.Exception(), tc.StackTrace()); 
     } 
    } 
}; 

當我調用該函數在XmlHttpRequest::open其中的「註冊」它的工作原理。所以起初我以爲對象被gc化了,但爲了確保它不會被收集在FunctionObj :: FunctionObj中,我從句柄創建了一個v8 :: Persistent。它仍然崩潰。我甚至讓v8 :: Persistent弱一點,看它是否真的被收集,但弱回調永遠不會被調用。

我在呼叫前右側檢查了其他的事情:

  1. V8 ::隔離:: GetCurrent() - >返回正確的,進入分離
  2. V8 ::語境:: GetCurrent() - >同
  3. 全球HandleScope不剩
  4. 的XmlHttpRequest ::開放,與呼叫拉姆達被稱爲在同一個線程

更多信息: 這不僅限於v8 :: Handle < v8 :: Function> only。如果我嘗試存儲對象並稍後訪問其中一個屬性,也會發生這種情況。我只是不能使用那個使用句柄的lambda中的任何東西。

+0

不知道這是否有幫助,但如果您存儲對象並希望稍後訪問其屬性,請嘗試使用持久指針類型。例如 持久 module_handle =持久 :: New(target); –

+0

它有幫助。這不是直接導致問題的直接原因(因爲我已經嘗試了持久的解決方案),但它讓我繼續走下去,這是一條正確的路,請參閱我的答案。 – Muepe

回答

0

正如我在試過的東西中所說的,我看了一下v8::Persistent。原來我用錯了。

我所做的:

class FunctionObj 
{ 
    v8::Handle<v8::Value> mHandle; 
    v8::Persistent<v8::Value> mPersistent; 
public: 
    FunctionObj(v8::Handle<v8::Value>& fun) { 
     mPersistent.Reset(v8::Isolate::GetCurrent(), fun); 
     mHandle = fun; 
    } 

    FunctionObj() { } 

    operator bool() { 
     return mHandle.IsEmpty() == false; 
    } 

    template<typename... Args> 
    void callVoid(const Args&... args) { 
     std::vector<v8::Handle<v8::Value>> arguments; 
     addArgument(arguments, args...); 

     v8::TryCatch tc; 
     v8::Handle<v8::Function>::Cast(mHandle)->Call(mHandle, arguments.size(), arguments.data()); 
     if (tc.HasCaught()) { 
      throw JS::Exception(tc.Exception(), tc.StackTrace()); 
     } 
    } 
}; 

我應該做的

class FunctionObj 
{ 
    v8::Persistent<v8::Value> mPersistent; 
public: 
    FunctionObj(v8::Handle<v8::Value>& fun) { 
     mPersistent.Reset(v8::Isolate::GetCurrent(), fun); 
    } 

    FunctionObj() { if(mPersistent) { mPersistent.Dispose(); } } 

    operator bool() { 
     return mHandle.IsEmpty() == false; 
    } 

    template<typename... Args> 
    void callVoid(const Args&... args) { 
     std::vector<v8::Handle<v8::Value>> arguments; 
     addArgument(arguments, args...); 

     v8::Local<v8::Function> fun = v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), mPersistent.As<v8::Function>()); 

     v8::TryCatch tc; 
     fun->Call(fun, arguments.size(), arguments.data()); 
     if (tc.HasCaught()) { 
      throw JS::Exception(tc.Exception(), tc.StackTrace()); 
     } 
    } 
}; 

我創建了持久並不意味着我存儲在手柄不被摧毀,但只稍後將有可能查詢該對象的新句柄並且該對象不會被刪除。

現在所有的作品都像一個魅力!