-
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