问题描述
我正在iPod touch设备上运行我的iOS应用程序并且即使总分配峰值仅为7 MB ,我也会收到内存警告,如下所示(当按下游戏场景时会发生这种情况):
我觉得奇怪是:
-
左峰(在时间0.00)对应于20 MB的内存分配(简介场景),尽管如此,不会给出任何内存警告。
-
中心峰值(在时间35.00)对应于分配的7 MB内存(正在推动游戏场景)并且会给出内存警告。
如果总内存只有7 MB,我不明白为什么会收到这些警告。这是正常的吗?我该如何避免这种情况?
查看分配密度,我们可以看到以下模式,对于我来说,在推动介绍场景的时刻(0.00)和游戏场景被推动的时刻(35.00)。 由于密度峰值相似,我认为记忆警告是由于我无法发现的其他东西。
编辑:
我一直在建议使用活动监视器,但不幸的是我的应用程序在加载游戏场景时崩溃仅分配了30 MB的内存。以下是活动监控报告。
查看报告,我可以看到总实际内存使用量总和约为105 MB。鉴于这应该参考RAM内存并且鉴于我的模型应该有的表现。
编辑2:我也更多关注SpringBoard,其虚拟内存使用量为180 MB。这是正常的吗?我发现了一些,似乎表明SpringBoard负责自动释放对象(它应该是管理屏幕和家庭按钮的过程,但我不确定它是否也与内存管理有关)。这是正确的吗?
另一个注意事项。我正在使用ARC。但是我不确定这会对问题做多少,因为没有明显的内存泄漏,XCode应该转换代码,将release / dealloc / retain调用添加到已编译的二进制文件中。
编辑3:如前所述,我使用ARC和Cocos2d(2.0)。我一直在玩Activity监视器。我发现如果我删除GameCenter身份验证机制,那么活动监视器运行正常(新疑点:是否有其他人遇到类似问题?GameCenter身份验证视图是否保留在某处?)。但是我注意到每次我在GameScene(初始场景 - >角色选择 - >行星选择 - >角色选择 - >行星选择 - >等等 - >字符选择......)之前的各种场景中前后导航。 REAL MEMORY用法会增加。过了一会儿,我开始得到内存警告,应用程序被iOS杀死。现在问题是:
- >我是否以正确的方式替换场景?我从各种场景中调用以下内容:
[[CCDirector sharedDirector] replaceScene:[MainMenuScene scene]];
我有 Cocos2d 2.0作为静态库而且replaceScene的代码是这个:
- (void)replaceScene:(CCScene *)scene
{
NSAssert(scene!=零,@参数必须是非零的);
NSUInteger index = [scenesStack_ count];
sendCleanupToScene_ = YES;
[scenesStack_ replaceObjectAtIndex:index-1 withObject:scene];
nextScene_ = scene; // nextScene_是弱参考
}
我想知道某个场景是不是得到了解除分配。我验证了正在调用清理方法但是我还在CCLayer dealloc方法上添加了 CCLOG调用并重建了静态库。结果是dealloc方法似乎没有被称为。
这是正常的吗? :D
我发现其他人。我想知道它是否与我真的需要花一些时间研究这个,除非从编辑3,任何人都可以告诉我我做错了什么: - )
我通过在控制台中添加进程有效内存使用量的打印来解决这个问题。通过这种方式,我可以精确测量App流程使用的实际内存。使用仪器被证明是不精确的,因为使用的实际内存与仪器上显示的内存不匹配。
此代码可用于获取有效的内存使用情况:
- (vm_size_t)report_memory
{
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)& info,
& size);
if(kerr == KERN_SUCCESS){
} else {
NSLog(@与task_info()的错误:%s,mach_error_string(kerr));
}
返回info.resident_size;
}
I am running my iOS App on iPod touch device and I get memory warnings even if the total allocation peak is only 7 MB as shown below (this happens when the Game Scene is pushed):
What I find strange is that:
the left peak (at time 0.00) corresponds to 20 MB of memory allocated (Introduction Scene) and despite this DOES NOT give any memory warning.
the central peak (at time 35.00) corresponds to raughly 7 MB of memory allocated (Game Scene is being pushed) and DOES give memory warning.
I do not understand why I get those warnings if the total memory is only 7 MB. Is this normal? How can I avoid this?
Looking at the allocation density we can see the following schema, which (to me) does not show much difference between the moment when the Intro Scene is being pushed (0.00) and the moment in which the Game Scene is being pushed (35.00). Being the density peaks similar I would assume that the memory warnings are due to something else that I am not able to spot.
EDIT:
I have been following a suggestion to use "Activity monitor" instead but unfortunately my App crashes when loading the Game Scene with only 30 MB of memory allocated. Here is the Activity monitor report.
Looking at the report I can see a total real memory usage sum of about 105 MB. Given this should refer to RAM memory and given my model should have 256 MB of RAM this should not cause APP crashes or Memory leaks problems.
I run the Leak monitor and it does not show any leak on my App. I also killed all the other apps.
However, analyzing the report, I see an astonishing 167 MB of Virtual Memory value associated to my App. Is this normal? What does that value mean? Can this be the reason for the crash? How can I detect which areas of my code are responsible for this?
My iPod is a 4th Generation model with 6.4 GB of capacity (memory) and only 290 MB of memory free. I am not sure if this somehow effects the Virtual Memory paging performance.
EDIT 2: I have also looked more at SpringBoard and its Virtual Memory usage is 180 MB. Is this normal? I found some questions/answers that seem to suggest that SpringBoard is responsible for autoreleasing objects (it should be the process for managing the screen and home botton but I am not sure if it has also to do with memory management). Is this correct?
Another note. I am using ARC. However I am not sure this has to do much with the issue as there are no apparent memory leaks and XCode should convert the code adding release/dealloc/retain calls to the compiled binary.
EDIT 3: As said before I am using ARC and Cocos2d (2.0). I have been playing around with the Activity monitor. I found out that if I remove the GameCenter authentication mechanism then the Activity Monitor runs fine (new doubt: did anyone else had a similar issue? Is the GameCenter authentication view being retained somewhere?). However I noticed that every time I navigate back and forwards among the various scenes prior the GameScene (Initial Scene -> Character Selection -> Planet Selection -> Character Selection -> Planet Selection -> etc.. -> Character Selection ..) the REAL MEMORY usage increases. After a while I start to get memory warnings and the App gets killed by iOS. Now the question is:
-> am I replacing the scenes in the correct way? I call the following from the various scene:
[[CCDirector sharedDirector] replaceScene: [MainMenuScene scene]];
I have Cocos2d 2.0 as static library and the code of replaceScene is this:
-(void) replaceScene: (CCScene*) scene
{
NSAssert( scene != nil, @"Argument must be non-nil");
NSUInteger index = [scenesStack_ count];
sendCleanupToScene_ = YES;
[scenesStack_ replaceObjectAtIndex:index-1 withObject:scene];
nextScene_ = scene; // nextScene_ is a weak ref
}
I wonder if somehow the scene does not get deallocated properly. I verified that the cleanup method is being called however I also added a CCLOG call on the CCLayer dealloc method and rebuild the static library. The result is that the dealloc method doesn't seem to be called.
Is this normal? :D
I found that other people had similar issues. I am wondering if it has to do with retain cycles and self blocks. I really need to spend some time studying this unless, from EDIT 3, anyone can tell me already what I am doing wrong :-)
I solved this by adding a print of the process effective memory usage in the console. In this way I could get a precise measurament of the real memory used by the App process. Using instrument proved to be imprecise as the real memory used did not match with the one shown on instruments.
This code can be used to get the effective memory usage:
-(vm_size_t)report_memory
{
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
} else {
NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}
return info.resident_size;
}
这篇关于为什么我只分配7 MB内存就会收到内存警告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!