Javascript v8-HeapObject::GetHeap()中崩溃-未初始化值
我从JS调用C++函数,如下所示:Javascript v8-HeapObject::GetHeap()中崩溃-未初始化值,javascript,c++,v8,Javascript,C++,V8,我从JS调用C++函数,如下所示: var req = new IO.HttpRequest(IO.RequestType.get); req.data({ i: 'jTKvNf9w' }).send('http://pastebin.com/raw.php', function (content) { console.log(content); }); void XmlHttpRequest::open(const Utils::String& str, ::JS::Function
var req = new IO.HttpRequest(IO.RequestType.get);
req.data({ i: 'jTKvNf9w' }).send('http://pastebin.com/raw.php', function (content) { console.log(content); });
void XmlHttpRequest::open(const Utils::String& str, ::JS::FunctionObjPtr callback) {
mCallback = callback;
mRequest->open(str);
}
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());
}
}
};
请求以异步方式处理,完成后调用回调。在C++中,发送函数看起来如下:
var req = new IO.HttpRequest(IO.RequestType.get);
req.data({ i: 'jTKvNf9w' }).send('http://pastebin.com/raw.php', function (content) { console.log(content); });
void XmlHttpRequest::open(const Utils::String& str, ::JS::FunctionObjPtr callback) {
mCallback = callback;
mRequest->open(str);
}
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());
}
}
};
之后,如果请求完成:
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(this))->heap()时,我遇到了访问冲突代码>。这些是v8功能。问题是,HeapObject中的这个指针是0xCCCC,这意味着它是一个未初始化的值。这个
-指针来自存储在JS::FunctionObjPtr(std::shared\u ptr的typedef)中的句柄
起初我认为我的函数obj
有问题。我通过以下方式获得:
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);
}
当我在其“注册”的XmlHttpRequest::open
中调用函数时,它会工作。因此,一开始我认为对象会被gc'ed,但为了确保它永远不会在FunctionObj::FunctionObj中被收集,我从句柄创建了一个v8::Persistent。但它还是崩溃了。我甚至让v8::Persistent弱来看看它是否真的被收集,但是弱回调永远不会被调用
电话前我检查过的其他事项:
v8::Isolate::GetCurrent()->返回输入的正确隔离
v8::Context::GetCurrent()->相同
全局手柄镜未被保留
open和具有该调用的lambda在同一线程中被调用
进一步资料:
这不仅限于v8::Handle。如果我尝试存储一个对象并稍后访问它的一个属性,也会发生这种情况。我就是无法在使用手柄的lambda内部找到任何东西。正如我在尝试的内容中所说的,我查看了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());
}
}
};
类函数对象
{
v8::手柄手柄;
持久性mPersistent;
公众:
FunctionObj(v8::Handle&fun){
mPersistent.Reset(v8::Isolate::GetCurrent(),fun);
mHandle=乐趣;
}
FunctionObj(){}
运算符bool(){
返回mHandle.IsEmpty()==false;
}
模板
void callVoid(常量参数和…参数){
向量参数;
添加参数(参数、参数…);
v8::TryCatch tc;
v8::Handle::Cast(mHandle)->调用(mHandle,arguments.size(),arguments.data());
if(tc.hascapt()){
抛出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());
}
}
};
类函数对象
{
持久性mPersistent;
公众:
FunctionObj(v8::Handle&fun){
mPersistent.Reset(v8::Isolate::GetCurrent(),fun);
}
FunctionObj(){if(mPersistent){mPersistent.Dispose();}
运算符bool(){
返回mHandle.IsEmpty()==false;
}
模板
void callVoid(常量参数和…参数){
向量参数;
添加参数(参数、参数…);
v8::Local fun=v8::Local::New(v8::Isolate::GetCurrent(),mPersistent.As());
v8::TryCatch tc;
fun->Call(fun,arguments.size(),arguments.data());
if(tc.hascapt()){
抛出JS::Exception(tc.Exception(),tc.StackTrace());
}
}
};
我创建的持久性并不意味着我存储的句柄不会被销毁,而是意味着以后可以查询对象的新句柄,并且对象不会被删除
现在一切都像一个符咒 不知道这是否有帮助,但如果您存储对象并希望稍后访问其属性,请尝试使用持久指针类型。e、 g.持久化模块_handle=Persistent::New(目标);这有帮助。这并不是问题的直接原因(因为我已经尝试了持久性解决方案),但它让我继续坚持下去,这是正确的方向,请看我的答案。