应用程序在内存不足后关闭。仪器截图里面
Posted
技术标签:
【中文标题】应用程序在内存不足后关闭。仪器截图里面【英文标题】:App closes after running out of memory. Instruments screenshot inside 【发布时间】:2012-09-17 12:05:02 【问题描述】:这是我通过仪器运行我的应用程序时得到的。它正在处理大量核心数据。我可以看到这显然是不对的,但我真的不知道这个屏幕截图告诉我什么。似乎是什么问题?如果您有兴趣,浓缩后的代码是这样的:
NSFetchRequest *oldFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *oldEntryEntity = [NSEntityDescription entityForName:@"Entry"
inManagedObjectContext:oldContext];
[oldFetchRequest setEntity:oldEntryEntity];
int numberOfEntries = [oldContext countForFetchRequest:oldFetchRequest error:nil];
int batchSize = 4;
[oldFetchRequest setFetchLimit:batchSize];
int offset = 0;
while (numberOfEntries - offset > 0)
@autoreleasepool
[oldFetchRequest setFetchOffset:offset];
NSError *error;
NSArray *entries = [oldContext executeFetchRequest:oldFetchRequest error:&error];
for (NSManagedObject *entry in entries)
@autoreleasepool
Entry *newEntry = [NSEntityDescription insertNewObjectForEntityForName:@"Entry"
inManagedObjectContext:newContext];
newEntry.entryID = [entry valueForKey:@"entryID"];
NSMutableOrderedSet *newMediaSet = [[NSMutableOrderedSet alloc] init];
NSOrderedSet *mediaSet = [entry valueForKey:@"media"];
int i = 0;
for (NSManagedObject *media in mediaSet)
Media *newMedia = [NSEntityDescription insertNewObjectForEntityForName:@"Media"
inManagedObjectContext:newContext];
newMedia.isInPhotoLibrary = [media valueForKey:@"isInPhotoLibrary"];
newMedia.positionInEntry = [NSNumber numberWithDouble:i + 1];
MediaImageData *imageData = [NSEntityDescription insertNewObjectForEntityForName:@"MediaImageData"
inManagedObjectContext:newContext];
imageData.data = [media valueForKey:@"originalImage"];
newMedia.imageData = imageData;
newMedia.entry = newEntry;
[newMediaSet addObject:newMedia];
i++;
newEntry.media = newMediaSet;
[newContext save:&error];
offset = offset + batchSize;
编辑:我按照这里给出的建议,将它包装在@autoreleasepools(我已经在上面编辑过)中,发生这种情况后它仍然崩溃:
它显然比第一次更深入代码,但它仍然崩溃。
【问题讨论】:
不要删除重要的代码。然后我们必须猜测正在发生的事情。您的获取请求甚至没有正确设置。另外,我看不到您在哪里添加了自动释放池...您的数据库有多大?您的媒体集及其包含的图像有多大?你在任何地方都抓着物体吗?您是否完全清除了上下文? 我现在已经放入了自动释放池。媒体集中的图像是标准图像的大小,我猜每个大约 1mb,具体取决于照片。在上面的代码之外,我没有做任何与此相关的事情。我没有清除上下文。 【参考方案1】:不讨论代码的效率:
将您的代码包装在 @autoreleasepool
中,用于外部 (while) 和内部 (for) 循环。
否则,您只是分配大量内存并仅在外部事件循环到达其循环结束时释放它。
【讨论】:
谢谢,我试试看。你能讨论我的代码的效率吗?我很想知道如何才能做得更好。【参考方案2】:尝试将快速枚举(for
循环)的内部包裹在@autoreleasepool
中,这应该会有所帮助。当更改达到危险的内存消耗时,您还可以运行某种计数器以将上下文保存在循环中。
你确实有很多对象,考虑优化你的数据结构。
【讨论】:
【参考方案3】:首先,关于发布 Core Data 相关问题的一些建议。几乎没有太多的信息。当您省略细节时,人们很难为您提供帮助,因为可能的互动太多了。
仅查看您发布的代码,就会留下很多问题。
我希望查看按总体大小排序的信息,而不是按分配数量排序的信息。这将更容易地告诉您内存在哪里使用。实际上,我看不到那张图片中的内存在哪里使用(然后再次 - 老眼睛 - 当我放大它时,它变得太模糊了)。
如果您认为它与核心数据有关,为什么不运行核心数据工具?
关于一些诊断帮助。
您的新 MOC 是直接连接到 PSC 还是有父 MOC。如果它有一个父 MOC,那么保存只是被推送到父 MOC 中,并且会一直保留在内存中,直到保存被持久化到数据库中。
您的 mediaSet 中有多少项?可能有很多这些,这可能会占用内存。
您对 FetchRequest 和 MOC 应用了哪些参数?基于这些选项,MOC 可以保留对象。检查这一点的一种方法是记录每个 MOC 的保留/插入/删除/等集的计数。通过记录这些,您可以查看任何一个 MOC 是否持有您认为不应该持有的东西。
然后您就可以知道是否需要刷新/重置您的 MOC。
您可以作弊,并在保存后致电[moc reset]
,但最好能看到这样做之前/之后的数字,这样您就可以说服自己记忆在哪里。
做更多的调试。为自己提供更多信息,以便您做出正确的决定……它也会为我们提供更好的信息来帮助您。
编辑
哎呀。我删除了关于可能没有太多内存的 cmets。看着那张照片上的小字,我的老眼睛对我毫无帮助。
编辑
谢谢。如何记录保留/插入/删除集的计数 对于每个 MOC? ——安德鲁
MOC 有几个属性(registeredObjects
、insertedObjects
、deletedObjects
、updatedObjects
)提供一组与这些类别匹配的对象。只需NSLog
每个类别中的对象数。您可以看到,对于每个 MOC,MOC 在一段时间内跟踪了多少对象。
另外,启用核心数据工具。它们的信息量很大。
【讨论】:
谢谢。如何记录每个 MOC 的保留/插入/删除集的计数?以上是关于应用程序在内存不足后关闭。仪器截图里面的主要内容,如果未能解决你的问题,请参考以下文章
虚拟内存地址空间不足(Borland C++ Builder 6 程序)