addSkin 内存泄漏 问题

使用addSkin(weapon)后,如果不手动release weapon,就会出现内存泄漏。

通过调试发现引用计数在addSkin后由1变成了3,然后在role销毁后,计数变成2,但如果只release 1次还是内存泄漏,我只能手动release 2次。

---------- Block 1380 at 0x065D36D0: 1280 bytes ----------
Leak Hash: 0x1F7E9738, Count: 1, Total 1280 bytes
Call Stack (TID 10000):
MSVCR120.dll!operator new()
f:\dd\vctools\crt\crtw32\heap\newopnt.cpp (18): MysteryDomain.exe!operator new() + 0xC bytes
g:\source_code\cocos\mysterydomain\classes\weapon\sabre\dirk.h (8): MysteryDomain.exe!Dirk::create() + 0x4C bytes
g:\source_code\cocos\mysterydomain\classes\sql.cpp (617): MysteryDomain.exe!Sql::getWeaponWithClassName() + 0x1D bytes
g:\source_code\cocos\mysterydomain\classes\sql.cpp (413): MysteryDomain.exe!Sql::getWeaponWithId() + 0x25 bytes
g:\source_code\cocos\mysterydomain\classes\sql.cpp (558): MysteryDomain.exe!Sql::getRoleWithId() + 0xF bytes
g:\source_code\cocos\mysterydomain\classes\sql.cpp (462): MysteryDomain.exe!Sql::getHeroWithId() + 0x18 bytes
g:\source_code\cocos\mysterydomain\classes\gamescene.cpp (107): MysteryDomain.exe!GameScene::getData() + 0x14 bytes
g:\source_code\cocos\mysterydomain\classes\gamescene.cpp (52): MysteryDomain.exe!GameScene::onEnter()
libcocos2d_2013.dll!cocos2d::Node::onEnter() + 0x72 bytes
g:\source_code\cocos\mysterydomain\proj.win32\main.cpp (34): MysteryDomain.exe!wWinMain() + 0x19 bytes
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (618): MysteryDomain.exe!__tmainCRTStartup() + 0xE bytes
kernel32.dll!BaseThreadInitThunk() + 0x12 bytes
ntdll.dll!RtlInitializeExceptionChain() + 0x63 bytes
ntdll.dll!RtlInitializeExceptionChain() + 0x36 bytes
Data:
D4 F0 07 01 02 00 00 00 55 13 00 00 00 00 00 00 … U…
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 … …
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 … …
00 00 80 3F 00 00 80 3F 00 00 80 3F 00 00 80 3F …?..? …?..?
00 00 96 42 00 00 00 C0 00 00 00 00 00 00 00 00 …B… …
00 00 00 00 00 00 AD BA 00 00 00 00 00 00 00 00 … …
00 00 ED 42 00 00 94 41 00 00 00 3F 00 00 00 3F …B…A …?..?
00 00 6D 43 00 00 14 42 01 F0 AD BA 00 00 80 3F …mC…B …?
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 … …
00 00 80 3F 00 00 00 00 00 00 00 00 00 00 00 00 …?.. …
00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 …? …
00 00 00 00 00 00 00 00 00 00 80 3F 00 00 80 3F … …?..?
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 … …
00 00 80 3F 00 00 00 00 00 00 00 00 00 00 00 00 …?.. …
00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 …? …
00 00 00 00 00 00 00 00 00 00 80 3F 01 F0 AD BA … …?..

---------- Block 1381 at 0x065DE648: 32 bytes ----------
Leak Hash: 0x9E416F5F, Count: 1, Total 32 bytes
Call Stack (TID 10000):
MSVCR120.dll!operator new()
f:\dd\vctools\crt\crtw32\heap\newopnt.cpp (18): MysteryDomain.exe!operator new() + 0xC bytes
g:\source_code\cocos\mysterydomain\classes\attackdata.h (17): MysteryDomain.exe!AttackData::create() + 0x49 bytes
g:\source_code\cocos\mysterydomain\classes\utils.cpp (396): MysteryDomain.exe!Utils::getAttackSprite() + 0x5 bytes
g:\source_code\cocos\mysterydomain\classes\weapon\sabre.cpp (22): MysteryDomain.exe!Sabre::initAttackSprite() + 0x81 bytes
g:\source_code\cocos\mysterydomain\classes\weapon\weapon.cpp (38): MysteryDomain.exe!Weapon::setRole() + 0x12 bytes
g:\source_code\cocos\mysterydomain\classes\role\role.cpp (746): MysteryDomain.exe!Role::setWeapon()
g:\source_code\cocos\mysterydomain\classes\sql.cpp (562): MysteryDomain.exe!Sql::getRoleWithId()
g:\source_code\cocos\mysterydomain\classes\sql.cpp (462): MysteryDomain.exe!Sql::getHeroWithId() + 0x18 bytes
g:\source_code\cocos\mysterydomain\classes\gamescene.cpp (107): MysteryDomain.exe!GameScene::getData() + 0x14 bytes
g:\source_code\cocos\mysterydomain\classes\gamescene.cpp (52): MysteryDomain.exe!GameScene::onEnter()
libcocos2d_2013.dll!cocos2d::Node::onEnter() + 0x72 bytes
g:\source_code\cocos\mysterydomain\proj.win32\main.cpp (34): MysteryDomain.exe!wWinMain() + 0x19 bytes
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (618): MysteryDomain.exe!__tmainCRTStartup() + 0xE bytes
kernel32.dll!BaseThreadInitThunk() + 0x12 bytes
ntdll.dll!RtlInitializeExceptionChain() + 0x63 bytes
ntdll.dll!RtlInitializeExceptionChain() + 0x36 bytes
Data:
14 C2 08 01 01 00 00 00 59 13 00 00 00 00 00 00 … Y…
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 … …

经过我的排查,发现出现这个的原因大概是:role存储在单例类中,当单例类析构时才会去调用role的release,而关闭游戏时,autorelease的类在data单例类之前就已经被销毁,无法再管理内存,这时需要手动销毁role中的weapon子sprite。我的解决代码如下
Role::~Role()
{
_fsm->release();

for (auto & weapon : _weapons)
    if (weapon)
    {
        weapon->removeFromParentAndCleanup(true);
    }

}

纯属个人水平差,不是引擎问题