辛苦了, 上传时间惊到我了.
合并完之后还是崩溃
加我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没关系。
赞!
有个疑问,在native对象释放后,seobj回收之前,seobj里仍然保留了native对象的指针(野指针),如果js代码恰好在这期间访问了这个对象,会不会crash?
最新1.8.1的安卓有内存泄漏啊,估计是龙骨这块,玩一会儿必定闪退