Skip to content
isdnetworks
Go back

한 곳만 고쳤더니 다른 길에서 또 났다

게임을 끝내고 나가면 가끔 죽었다. 원인을 찾아 고쳤는데 며칠 뒤 다른 자리에서 같은 것이 났다.

Table of contents

Open Table of contents

한 곳을 고쳤다

Cocos2d-x 의 onExit() 에서 적 노드의 동작을 멈추고 있었다. 그 시점에 노드가 이미 정리된 경우가 있었다.

CCNode.h 주석에도 적혀 있다. onExit 중에는 형제 노드에 접근할 수 없다는 것이다.

if (m_enemy) {
    m_enemy->stopAllActions();
    m_enemy = NULL;
}

있는지 확인하고 쓰게 하고 쓴 뒤에는 비워 뒀다. 이걸로 그 자리는 안 죽었다.

다른 자리에서 또 났다

며칠 뒤 보스전에서 같은 것이 났다. grep -rn "onExit" 으로 열어 보니 같은 모양이 확인 없이 그대로 있었다.

처음 고칠 때 이 자리를 안 봤다. onExit() 을 넣은 곳이 14 곳이었다. 하나씩 열어 보니 넷이 더 같은 모양이었다.

한 자리를 고쳤으면 같은 모양이 어디 또 있는지 세는 것이 다음 일이었다.

잊을 자리를 없앴다

찾아서 고치는 것으로는 다음에 또 생긴다. 새 화면을 만드는 사람이 그 확인을 안 넣으면 그만이기 때문이다.

CCLayer 를 상속한 공통 부모를 두고 onExit() 에서 하는 일을 거기에 모았다. 각 화면은 자기가 들고 있는 것만 적는다.

virtual void onExit() {
    CCLayer::onExit();
    releaseNodes();
}

확인하는 것 자체는 Cocos2d-x 에 이미 있었다. CCPlatformMacros.hCC_SAFE_RELEASE_NULL 이 그대로 그 모양이다.

#define CC_SAFE_RELEASE_NULL(p)  if(p) { p->release(); p = 0; }

손으로 쓰던 if 를 이걸로 바꾸니 빠뜨릴 자리가 없어졌다.

확인하는 코드에는 왜 확인하는지도 적었다. 이유가 없으면 필요 없어 보인다며 지우는 사람이 나온다. onExit()CCScene 이 바뀔 때도 불리고 자식 노드가 먼저 정리된 뒤에도 불린다. 그것을 주석에 남겼다.

가끔 나는 것을 개발 중에 만나게

문제는 이게 가끔만 났다는 것이다. 개발 중에는 잘 안 나서 고쳤는지도 확인이 어려웠다.

CCAssert 를 넣었다. COCOS2D_DEBUG 가 켜진 빌드에서만 돌고, 이미 정리된 노드를 만지면 그 자리에서 멈춘다. 조용히 지나가면 나중에 다른 자리에서 죽고 원인이 안 보인다.

가끔 나는 것은 가끔 안 나는 것이 아니라 조건이 맞을 때만 나는 것이다. 그 조건을 개발 중에 만나게 하는 것이 방법이었다.

onExit() 에서 정리할 것이 더 있는지도 같이 봤다. 넷이었는데 둘만 하고 있었다.

CCScheduler   unscheduleAllSelectorsForTarget(this)
CCTouchDispatcher  removeDelegate(this)
콜백 등록      직접 지움
SimpleAudioEngine  stopAllEffects()

removeDelegate 를 안 부르면 사라진 객체로 터치가 간다. 한 자리로 모은 김에 빠진 것도 넣었는데, 모으지 않았으면 각 파일에서 무엇이 빠졌는지 못 봤을 것이다.

정리


Share this post on:

Previous Post
지우고 다시 깔라고 안내했다
Next Post
배포 빌드가 다르게 돌았다