1.7.0正式版,1.8.0正式版,1.7.2beta2都会在IOS中频繁闪退,Android中却没事

辛苦了, 上传时间惊到我了.

合并完之后还是崩溃

:sweat_smile:

加我QQ吧,私信发你。

每日一顶,等解决了好上线

加好友请求 已发

每日一顶+1

有结果了吗?

每日一顶

jsb2.0对于cpp管理js生命周期的对象,处理的有问题。如果用到了spine, box2d等,可能会导致crash(ios,android和win32都可能crash)。修改后最近几天没有crash过了。最近太忙没时间提交pullrequest,有问题的同学可以自己修改下试试(引擎中有多处)。

文档里的

spTrackEntry_setDisposeCallback([](spTrackEntry* entry){
    // spTrackEntry 的销毁回调
    auto cleanup = [entry](){
        if (!se::ScriptEngine::getInstance()->isValid())
            return;
        se::AutoHandleScope hs;
        se::ScriptEngine::getInstance()->clearException();
        auto iter = se::NativePtrToObjectMap::find(entry);
        if (iter != se::NativePtrToObjectMap::end())
        {
            CCLOG("spTrackEntry %p was recycled!", entry);
            se::Object* seObj = iter->second;
            seObj->clearPrivateData(); // 解除 mapping 关系
            seObj->unroot(); // unroot,使 JS 对象受 GC 管理
            seObj->decRef(); // 释放 se::Object
        }
    };
    // 确保不再垃圾回收中去操作 JS 引擎的 API
    if (!se::ScriptEngine::getInstance()->isGarbageCollecting())
    {
        cleanup();
    }
    else
    { // 如果在垃圾回收,把清理任务放在帧结束中进行
        CleanupTask::pushTaskToAutoReleasePool(cleanup);
    }
});

应该改成类似这样的:

virtual void on_destroyed(void *obj) {        
    auto iter = se::NativePtrToObjectMap::find(obj);
    if (iter == se::NativePtrToObjectMap::end())
        return;
    auto seInstance = se::ScriptEngine::getInstance();
    if (!seInstance->isValid() || seInstance->isInCleanup())
        return;
    se::AutoHandleScope hs;
    seInstance->clearException();
    se::Object* seObj = iter->second;
    seObj->clearPrivateData();
    auto cleanup = [seObj]() {
        auto seInstance = se::ScriptEngine::getInstance();
        if (!seInstance->isValid() || seInstance->isInCleanup())
            return;
        se::AutoHandleScope hs;
        se::ScriptEngine::getInstance()->clearException();
        seObj->unroot();
        seObj->decRef();
    };
    if (!se::ScriptEngine::getInstance()->isGarbageCollecting())
    {
        cleanup();
    }
    else
    {
        CleanupTask::pushTaskToAutoReleasePool(cleanup);
    }
}

你这个修复主要是加入了 seInstance->isInCleanup() ?

你碰到的crash问题主要是在热更新重启游戏的时候么?

还有,你吧 clearPrivateData 移动到cleanup 外面是有问题的,因为如果当前是在 GarbageCollecting,操作任何有关JS VM的接口都可能导致问题的。

主要是把clearPrivateData()放到cleanup()外面。

不是。cpp控制生命周期的对象,反复创建销毁的时候,会出现assert(NativePtrToObjectMap::find(data) == NativePtrToObjectMap::end());失败的问题。

如果一个native对象销毁了,但是正在垃圾回收,那么cleanup会被延迟调用。这期间它之前占用的内存可能会被分配给新的对象,这个新的对象在setPrivateData()的时候就会assert失败。

重现的testcase也很简单,只要重复的“创建native对象,生成相应的SEObject,销毁native对象”就可以了。

这一点我倒是不清楚。不过修改之前是必然crash,修改之后暂时还没crash过。

正在garbage collectiing,是不能操作任何js vm接口,还是只是不能操作clearPrivateData()?
按我的理解,clearPrivateData()只是把js obj的private清空而已,并不会导致js obj被回收,理论应该不会有问题才对?而且代码中很多地方都有setPrivateData()的调用,似乎并没有判断是否正在garbage collecting?
当然我对vm内部不太了解,只是根据相关代码猜测的。

任何有关 JS VM 的包含context接口都不能调用。大部分接口都包含context的。

你反馈的 setPrivateData 触发assert 的确会有问题,这块我考虑一下如何修复更合理。

前面加了se::AutoHandleScope hs;也不可以的吗?

跟HandleScope没关系。

1赞

解决了

https://github.com/cocos-creator/cocos2d-x-lite/pull/1075

并更新了文档内容。

1赞

赞!

有个疑问,在native对象释放后,seobj回收之前,seobj里仍然保留了native对象的指针(野指针),如果js代码恰好在这期间访问了这个对象,会不会crash?

最新1.8.1的安卓有内存泄漏啊,估计是龙骨这块,玩一会儿必定闪退