修复DragonBones在游戏退出时候导致crash

  • Creator 版本:<= 1.9

  • 目标平台:native

  • 重现方式:

      let slot = this.armatureDisplay.armature().getSlot(slotName);
      if (slot) {
          if (slot._tj_childArmatureName !== armatureName) {
              let armature = this.armatureDisplay.buildArmature(armatureName);
              if (!armature)
                  throw new Error(`CANNOT buildArmature '${armatureName}'`);
              slot.childArmature = armature;
              slot._tj_childArmatureName = armatureName;
          }
      }
    

重点是slot.childArmature = armature; 会产生一个挂接, 在后续析构的时候这个挂接会被他的父亲一起析构. 而原来的代码会取析构这个子节点, 野指针.
所以在jsb_dragonbones_manual.cpp做了对应修改. 可以修复这个bug

#if 0
        // Copy the dragonbones object vector since vector element will be deleted in BaseObject destructor.
        std::vector<dragonBones::BaseObject*> allDragonBonesObjects = dragonBones::BaseObject::getAllObjects();
        SE_LOGD("Starting to cleanup dragonbones object, count: %d\n", (int)allDragonBonesObjects.size());
        // Clear dragonBones::Armature objects those are not in the pool because
        // dragonBones::Armature controls life cycle for lots of other objects,
        // so it needs to be disposed first.
        for (auto dbObj : allDragonBonesObjects)
        {
            if (dynamic_cast<dragonBones::Armature*>(dbObj) != nullptr && !dbObj->isInPool())
            {
                SE_LOGD("1. Force delete not in pool DragonBones Armature object: %s, %p\n", typeid(*dbObj).name(), dbObj);
                delete dbObj;
            }
        }
#else
        SE_LOGD("Starting to cleanup dragonbones object, count: %d\n", (int)dragonBones::BaseObject::getAllObjects().size());

        //1. collect all armature object
        std::set<dragonBones::Armature*> allArmatureObjects;
        for (auto dbObj : dragonBones::BaseObject::getAllObjects()) {
            if (dynamic_cast<dragonBones::Armature*>(dbObj) != nullptr && !dbObj->isInPool()) {
                allArmatureObjects.insert(dynamic_cast<dragonBones::Armature*>(dbObj));
            }
        }

        //2. collect all children armature object
        std::vector<dragonBones::Armature*> allChildrenArmatureObjects;
        for (dragonBones::Armature* armature : allArmatureObjects) {
            for (dragonBones::Slot* slot : armature->getSlots()) {
                for (const std::pair<void*, dragonBones::DisplayType>& pair : slot->getDisplayList()) {
                    if (pair.second == dragonBones::DisplayType::Armature) {
                        allChildrenArmatureObjects.push_back(static_cast<dragonBones::Armature*>(pair.first));
                    }
                }
            }
        }

        //3. in allArmatureObjects, remove all children armature 
        //SE_LOGD("children armature object num: %d\n", allChildrenArmatureObjects.size());
        for (auto armature : allChildrenArmatureObjects) {
            allArmatureObjects.erase(armature);
        }
        allChildrenArmatureObjects.clear();

        //4. delete the rest armature object
        for (auto armature : allArmatureObjects) {
            //SE_LOGD("1. Force delete not in pool DragonBones Armature object: %s, %p\n", typeid(*armature).name(), armature);
            delete armature;
        }
        allArmatureObjects.clear();

        //
        std::vector<dragonBones::BaseObject*> allDragonBonesObjects;
#endif
1赞

你好 请问这是哪里修改的 换装遇到闪退 但不确定是不是同一个问题

搜索if 0 部分的代码.

可以提交到git上啊,让后来的人免的又要采坑啊。。

还不会操作github

mark!