首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >v8 -HeapObject中的崩溃::GetHeap()-未初始化的值

v8 -HeapObject中的崩溃::GetHeap()-未初始化的值
EN

Stack Overflow用户
提问于 2014-04-04 07:57:15
回答 1查看 211关注 0票数 0

在JS中,我调用C++函数,如下所示:

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

请求将被异步处理,一旦完成,回调就会被调用。在C++中,发送函数如下所示:

代码语言:javascript
复制
void XmlHttpRequest::open(const Utils::String& str, ::JS::FunctionObjPtr callback) {
    mCallback = callback;
    mRequest->open(str);
}

如果请求完成后:

代码语言:javascript
复制
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-Pointer在HeapObject中是0xCCCCCC,这意味着它是一个未初始化的值。this-Pointer来自存储在JS::FunctionObjPtr中的句柄(std::shared_ptr的typedef )。

一开始我认为我的FunctionObj有问题。我是通过以下方式获得这一信息的:

代码语言:javascript
复制
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看起来如下所示:

代码语言:javascript
复制
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. ->返回正确的,输入的隔离
  2. v8::Context::GetCurrent() -> v8
  3. 全局HandleScope没有留下。
  4. XmlHttpRequest::open和带有调用的lambda在同一个线程中调用。

更多信息:这不仅限于v8::Handle。如果我试图存储一个对象并在以后访问它的一个属性,也会发生这种情况。我只是不能在那个用手柄的羔羊里面找到任何东西。

EN

回答 1

Stack Overflow用户

发布于 2014-04-04 11:20:46

正如我在我尝试过的事情中所说的,我看了一下v8::Persistent。结果发现我用错了。

我所做的:

代码语言:javascript
复制
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());
        }
    }
};

我应该做的

代码语言:javascript
复制
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());
        }
    }
};

我创建的持久化并不意味着我存储的句柄不会被销毁,只意味着以后可以查询对象的新句柄,并且对象不会被删除。

现在所有的一切都像一种魅力!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22856836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档