我很难找到内存泄漏。我正在使用cocos2d。这是两个类的数据区:
@interface Dungeon : CCLayerColor {
DungeonLevel *aDungeonLevel;
Player *thePlayer;
// list of all monster file names
NSMutableArray *monsterNames;
// array of how many monsters there are of each monster level
NSMutableArray *monsterLevels;
MessageView *theMessageView;
DungeonDisplay *theDisplay;
bool processing;
int currentDungeonLevel;
}
@interface DungeonDisplay : CCLayerColor {
NSMutableArray *displayGrid;
NSMutableArray *displayGrid2;
NSMutableArray *displayGrid3;
NSMutableArray *displayGrid4;
NSMutableArray *dungeonMatrix;
NSMutableArray *monsterSprites;
Dungeon *theDungeon;
int xdelt;
int ydelt;
CGPoint lowerLeft;
Player *thePlayer;
CCSprite *playerSprite;
CCSprite *mSprite1;
ButtonsLayer *buttonArea;
double previousTime;
double currentTime;
double touchTimePrev;
bool touchFlag;
bool processing;
bool processing2;
bool animating;
bool flipSprite;
bool doIdleAnimation;
bool isAttacking;
int firstIteration;
CGPoint dungeonOriginalPosition;
CGPoint playerOriginalPosition;
CGPoint mSprite1Original;
CGPoint buttonOriginal;
CCTimer *myTimer;
// List of Messages
NSMutableArray *messages;
int messageIndex;
// player transparency level
int transparency;
// indicates that walls need to become transparent
bool needTransparency;
int pXInc;
int pYInc;
int tempx;
int tempy;
// debugging variables
CCLabelTTF *debugLabel1;
CCLabelTTF *debugLabel2;
// the Map
MiniMap *aMap;
}
好的,现在Dungeon对象通过与另一个对象DungeonLevel交互来创建DungeonDisplay对象(我认为它与确定DungeonDisplay未被解除分配的原因特别相关)。这是创建“singleton”DungeonDisplay对象的所有代码:
-(void) displayDungeon
{
if (!theDisplay) {
theDisplay = [[DungeonDisplay alloc]init];
[self addChild:theDisplay z:101];
[theDisplay letTheDungeon:self];
}
else {
[thePlayer placePC:thePlayer.pCLocation];
[theDisplay displayStructure];
}
theDisplay.visible = true;
aDungeonLevel.visible = NO;
}
出于某种原因,在addChild(一个cocos方法)之后,保留计数跳转到4(从1开始)。 “letTheDungeon”对保留计数没有影响(如预期的那样)。
答案 0 :(得分:7)
问题:“我很难找到内存泄漏。...有没有人能够详细列出增加和减少保留计数的具体事项?”
答案:哇,很多东西。只关注增加保留计数的内容,它包括:添加子视图;推/控制器;添加到词典和数组;名称以alloc
,new
,copy
或mutableCopy
开头的任何方法;任何retain
次调用;在viewDidLoad
中的非ARC代码中创建对象,而忽略了在dealloc
中清理它们;在非ARC代码中的一个指针中分配另一个新对象,该指针已指向尚未释放的项目;任何核心基础在名称中使用create
或copy
;这可能只是划伤了表面。降低保留计数的列表同样长。
没有冒犯,这不太可能成为追踪泄漏的有效途径。 (这就像说有人在曼哈顿开枪一样,所以让我们拿一把东海岸的每个人拿着枪的清单。)我建议你采用更多的CSI方法:
通过Xcode static analyzer运行您的代码。在你解决所有这些问题之前,没有必要进一步研究。您应该从静态分析中获得零警告。
使用探查器工具find the leak。一旦您学会了如何使用该工具,它通常可以准确地向您显示哪个对象和代码行导致泄漏,此时分辨率更容易。
确保您完全阅读并理解Advanced Memory Management。如果您正在使用核心基础,请查看Memory Management Programming Guide for Core Foundation。
如果您没有使用ARC,请开始调试检查各种对象retainCount
的调试消息。
如果您发现一段泄漏的代码,如果您无法弄明白,请在StackOverflow上发布有问题的代码(确保告诉我们它是否为ARC),我们可以帮助您进一步诊断。
我真的不是故意嗤之以鼻,但这个问题,就目前来说,太宽泛了,我们无法帮助你(即使理论上有人能给你全面的答案,我也无法想象它会是对你有帮助)。希望上面提到的一些技巧会指出你正确的方向。
我真的很沮丧。你决定要认真追踪泄漏的第一个项目是一项痛苦的工作。你必须掌握Objective-C内存管理的重要世界,并学习一些相当复杂的工具(尤其是分析器)。但是,一旦你在一个大项目中完成了一次练习并掌握了这些工具,那么你将拥有那个“啊哈”的时刻,追踪内存泄漏将成为一个简单(或至少是有条不紊)的过程。
答案 1 :(得分:1)
第一个可能导致泄密的是你没有发布创建的theDisplay实例。将您的代码更改为
if (!theDisplay)
{
theDisplay = [[DungeonDisplay alloc]init];
[self addChild:theDisplay z:101];
[theDisplay release]; // add this line
[theDisplay letTheDungeon:self];
}
或
if (!theDisplay)
{
theDisplay = [[[DungeonDisplay alloc] init] autorelease]; // create autoreleased object
[self addChild:theDisplay z:101];
[theDisplay letTheDungeon:self];
}
它将解决至少一个内存问题。
答案 2 :(得分:1)
感谢您的所有答案。问题得到解决,我再次发现微不足道的泄漏。问题出在子类DungeonDisplay中的CCTouchDispatcher。我将用于处理触摸的代码更改为dungeon类,并进行了一些其他的小调整,并且每个dealloc都被调用。
无论如何,它的坚如磐石。我来回移动了一百次,分配的内存没有变化。事实上,我现在的巡航速度低于70 MB,比以前少了很多。
再次感谢,特别感谢您的鼓励和支持。
答案 3 :(得分:0)
好吧,这可能不是'科学'正确的,但有时你必须做你应该做的事情。使用Instruments Zombies工具如下。在代码中你知道已经泄漏了一个对象的某个地方,发出[theLeakedObject_ release]多次,就像僵尸一样。然后在乐器中,你将能够获得保留计数的痕迹,该类增加它,并按顺序减少它,直到明显你僵尸出来。您应该能够“找到”不应该存在的保留器,并从那里取出它。
PS。作为个人实践的问题,我在创建源自CCNode的对象时遵循Morion的建议练习并坚持使用自动释放分配模式。保持干净整洁,清理:YES流程擦拭我很好:)。对于任何其他商务舱,我特别保留/释放在科罗拉的自动释放池中留下尽可能多的空间。