我有一個街機風格的iPhone遊戲,它是用Cocos2d-iPhone構建的,並且工作正常,但它在無法預測的播放量之後沒有明顯的原因隨機崩潰。有時你可以在沒有問題的情況下玩幾個級別,而其他的玩家在幾秒鐘後就會崩潰。在XCode中有一些常見的行通常是EXC_BAD_ACCESS,它會提示一個內存事物,但是這些對象都是自動釋放的,並且有額外的保留,並且崩潰非常不一致。似乎適合的一件事是,隨着越來越多的事情發生崩潰的可能性增加,這再次表明一些內存問題,但是沒有應用程序內存警告被解僱。cocos2d隨機崩潰的可能原因是什麼?我如何追蹤它們?
一些示例崩潰線路有:
if(gameGlobals.gameState == GAME_STATE_PAUSED) {...}
if(![hearts isKindOfClass:[CCSprite class]]) {...}
但這兩行有一個是fune了好半天,直到崩潰全局對象。
所以,我的問題是,我該如何去追蹤這個問題,是否有可能的罪魁禍首?
謝謝。
UPDATE
我一直在做一點偵探工作,我至少有一定的一致性。我認爲有兩件事情正在進行:
1)是,用於檢測與像素數據刪除的對象像素完美衝突的數學正在烹飪CPU。
2)我有一些殭屍精靈,否則,正在釋放出我的意識。
當我添加一顆子彈雪碧我用:
CCSprite *bullet = [CCSprite spriteWithFile:@"bullet.png"];
bullet.tag = BULLET_TAG_GOODY;
bullet.position = ccp(player.position.x,50);
[self addChild:bullet];
[bullet runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:2 position:ccp(player.position.x,320)],
[CCCallFuncN actionWithTarget:self selector:@selector(bulletMoveFinished:)],
nil]];
[bullets addObject:bullet];
然後我遍歷數組子彈。目前它崩潰說我正試圖訪問一個釋放的實例。
所以,1)如何設置這個,所以我的精靈不會被釋放?從CCSprite中刪除autorelease是個好主意嗎? 2)探測子彈與太空入侵者風格基地的最佳方式是什麼?
目前:
if([self overlapBases: bullet.position.x :bullet.position.y :true]) {...}
-(bool)overlapBases :(GLfloat)x :(GLfloat)y :(bool)up {
// NSLog(@"overlapping - %f,%f",x,y);
if(y > 20 && y < 100) {
int bn = -1;
if(x > 28 && x < 118) {
bn = 0;
}
if(x>140 && x<230) {
bn = 1;
}
if(x>254 && x<343) {
bn = 2;
}
if(x>365 && x<453) {
bn = 3;
}
if(bn> -1) {
NSLog(@"overlapping - %f,%f",x,y);
// for (int ix = 0; ix < NUM_BASES; ix++) {
if (overLap(x, 2, aspeaker[bn].position.x, BASE_WIDTH * aspeaker[bn].scale)) {
if (overLap(y, 4, aspeaker[bn].position.y, BASE_HEIGHT * aspeaker[bn].scale)) {
NSLog(@"ix: %i, x: %f, y: %f",bn,x,y);
return [self fineCollision:bn :x :y :up];
}
}
}
}
return false;
}
-(bool)fineCollision :(GLuint)baseNum :(GLfloat)x :(GLfloat)y :(bool)up {
//convert bullet x and y passed in to this base coords
//check if solid
//if so, remove bits in gfx and array, return true
//else return false;
GLfloat bullx = (x - aspeaker[baseNum].position.x + BASE_WIDTH)/2.0;
GLfloat bully = (y - aspeaker[baseNum].position.y + BASE_HEIGHT)/2.0;
GLint testx = (GLint)bullx;
if ((testx < 0) | (testx >= BASE_WIDTH)) {
return false;
}
GLuint testy;
bool hit = false;
for (int iy = -2; iy < 2; iy++) {
testy = (GLint)(bully - iy);
if ((testy >= 0) & (testy < BASE_HEIGHT)) {
if (baseShape[baseNum][15 - testy][testx] > 0) {
if(showrm == YES) {
CCSprite *maskSprite = [CCSprite spriteWithFile:@"bullet-mask.png"];
[maskSprite setBlendFunc: (ccBlendFunc) {GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}];
maskSprite.position = ccp(x , y-(40+22-5));
NSLog(@"sprite: %f",maskSprite.position.x);
NSLog(@"render mask: %f",rm.frameInterval);
[rm addSpriteMask:maskSprite];
[rm drawCurrent];
}
[self remove:testx :testy :baseNum :up];
GLuint seed = rand()%64;
if (seed & 1) {
[self remove:testx - 1:testy - 1 :baseNum :up];
}
if (seed & 2) {
[self remove:testx - 1:testy :baseNum :up];
}
if (seed & 4) {
[self remove:testx - 1:testy + 1:baseNum :up];
}
if (seed & 8) {
[self remove:testx + 1:testy - 1:baseNum :up];
}
if (seed & 16) {
[self remove:testx + 1:testy :baseNum :up];
}
if (seed & 32) {
[self remove:testx + 1:testy + 1:baseNum :up];
}
hit = true;
}
}
}
return hit;
}
- (void)remove:(GLint)offX :(GLint)offY :(GLuint)baseNum :(bool)up {
if ((offX < 0) | (offX >= BASE_WIDTH)) {
return;
}
if ((offY < 0) | (offY >= BASE_HEIGHT)) {
return;
}
baseShape[baseNum][15 - offY][offX] = 0;
}
bool overLap(GLfloat x1, GLfloat w1, GLfloat x2, GLfloat w2) {
GLfloat left1, left2;
GLfloat right1, right2;
GLfloat halfWidth1 = w1 * 0.5f;
GLfloat halfWidth2 = w2 * 0.5f;
left1 = x1 - halfWidth1;
left2 = x2 - halfWidth2;
right1 = x1 + halfWidth1;
right2 = x2 + halfWidth2;
if (left1 > right2) {
return false;
}
if (right1 < left2) {
return false;
}
return true;
}
有關檢測和rendermask想到用大量的精靈和磨損的混合模式。
謝謝。
更新再次:)
好的,我發現了一些殭屍!
Address Category Event Type RefCt Timestamp Size Responsible Library Responsible Caller
0 0x13a00e90 CCSprite Malloc 1 00:32.974.212 432 SpacedInvaders +[CCSprite spriteWithFile:]
1 0x13a00e90 CCSprite Autorelease <null> 00:32.974.235 0 SpacedInvaders +[CCSprite spriteWithFile:]
2 0x13a00e90 CCSprite Retain 2 00:32.974.546 0 SpacedInvaders -[CCArray insertObject:atIndex:]
3 0x13a00e90 CCSprite Retain 3 00:32.974.629 0 SpacedInvaders -[CCActionManager addAction:target:paused:]
4 0x13a00e90 CCSprite Retain 4 00:32.974.634 0 SpacedInvaders -[CCArray addObject:]
5 0x13a00e90 CCSprite Release 3 00:32.986.279 0 QuartzCore CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long)
6 0x13a00e90 CCSprite Release 2 00:33.074.889 0 SpacedInvaders -[CCArray removeObject:]
7 0x13a00e90 CCSprite Release 1 00:33.074.915 0 SpacedInvaders -[CCActionManager deleteHashElement:]
8 0x13a00e90 CCSprite Release 0 00:33.074.918 0 SpacedInvaders -[CCArray removeObject:]
9 0x13a00e90 CCSprite Zombie -1 00:33.074.939 0 SpacedInvaders -[GameLayer update:]
那麼這裏發生了什麼?我發現保留數量過低,但我如何避免這種情況。我想我正在做一些愚蠢的順便說一句。
謝謝。
好,感謝到目前爲止評論。 – Martin
OK,感謝評論到目前爲止(再次)。要明確autoreleases是cocos2d核心代碼的一部分。殭屍已啓用,但沒有任何工具。沒有明顯的泄漏或其他(也可以看到)。 – Martin
殭屍是不是樂器,而不是他們改變EXC_BAD_ACCESS撞到上面寫着「XXXX送到YYYY的釋放實例」,幫助您找出問題的消息。也許這調試速成班可能幫助:http://www.learn-cocos2d.com/2011/10/xcode-4-debugging-crashcourse/ – LearnCocos2D