v8 - Crash in HeapObject::GetHeap() - 未初始化的值
v8 - Crash in HeapObject::GetHeap() - uninitialized value
从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); });
请求被异步处理,一旦完成,就会调用回调。在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);
});
}
推送帧将函数放入队列中,以便在设置所有脚本的主线程中执行。
现在问题出在 HeapObject::GetHeap() 调用 MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
时我收到访问冲突callVoid
。这些是 v8 函数。问题是,堆对象中的this
指针是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'ed了,但为了确保它永远不会被收集到FunctionObj::FunctionObj中,我从句柄创建了一个v8::P ersistent。它仍然崩溃。我什至将 v8::P ersistent 设置为弱,看看它是否真的被收集,但弱回调从未被调用。
我在通话前检查过的其他事项:
- v8::隔离::获取电流() -> 返回正确的、输入的隔离
- v8::上下文::GetCurrent() -> 相同
- 全局句柄范围未离开
- XmlHttpRequest::open 和带有调用的 lambda 在同一线程中调用
更多信息:这不仅限于 v8::Handle<v8::Function>。如果我尝试存储一个对象并稍后访问其属性之一,也会发生这种情况。我只是不能找到使用句柄的 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());
}
}
};
我应该做什么
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());
}
}
};
我创建的持久性并不意味着我存储的句柄不会被销毁,而只是以后可以查询对象的新句柄并且不会删除该对象。
现在一切都像魅力一样工作!
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- C++成员初始化
- 为什么在C++中首先初始化成员类
- 同时具有"聚合初始化"和"模板推导"
- 初始化具有非默认构造函数的std::数组项的更好方法
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 在C和C++中初始化结构中的数组
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 在函数内部的声明中初始化数组,并在外部使用它
- v8 - Crash in HeapObject::GetHeap() - 未初始化的值