简体   繁体   English

内存用完后,应用程序关闭。 仪器内部屏幕截图

[英]App closes after running out of memory. Instruments screenshot inside

在此处输入图片说明

This is what I get when I run my app through instruments. 这是通过仪器运行我的应用程序时得到的。 It's processing a lot of core data. 它正在处理许多核心数据。 I can see this obviously isn't right, but I don't really know what this screenshot is telling me. 我可以看到这显然是不对的,但是我真的不知道该屏幕快照告诉我什么。 What appears to be the problem? 似乎是什么问题? If you're interested, the code, condensed, is this: 如果您有兴趣,可以使用以下简明代码:

    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;
   }
}

EDIT: I followed the advice given here, wrapping it in @autoreleasepools (which i've edited in above), and it still crashed after this happened: 编辑:我按照这里给出的建议,将其包装在@autoreleasepools中(我在上面进行了编辑),并且在发生这种情况后仍然崩溃:

http://cl.ly/image/1U2T2p3w1X2Z

It obviously got further into the code than the first time, but it's still crashing. 它显然比第一次更深入了代码,但仍然崩溃。

Without discussing the efficiency of your code: 在不讨论代码效率的情况下:
Wrap your code in @autoreleasepool {} for both the outer (while) and inner (for) loops. 在外部循环(while)和内部循环(for)中,将代码包装在@autoreleasepool {}中。
Otherwise, you're just allocating a whole lot of memory and freeing it only when the outer event loop reaches it's end of loop. 否则,您仅分配大量内存,仅在外部事件循环到达循环结束时才释放它。

Try wrapping the insides of your fast enumeration ( for loop) in @autoreleasepool , that should help. 尝试将快速枚举( for循环)的内部包装在@autoreleasepool ,这会有所帮助。 You can also run some sort of counter to save your context inside the loop when changes reach dangerous memory consumption. 当更改达到危险的内存消耗时,您还可以运行某种计数器将上下文保存在循环中。

You sure do have a lot of objects though, think about optimising your data structure. 当然,您确实有很多对象,请考虑优化数据结构。

First, a bit of advice on posting Core Data related questions. 首先,有关发布核心数据相关问题的一些建议。 There is almost no such thing as too much information. 几乎没有信息太多的事情。 When you omit details, it makes it very difficult for people to help you because there are so many possible interactions. 当您省略细节时,由于存在许多可能的互动,因此人们很难为您提供帮助。

Just looking at the code you posted, it leaves so many questions. 仅查看您发布的代码,就会留下很多问题。

I would want to see the information sorted by overall size, not number of allocations. 我想查看按总体大小而不是分配数量排序的信息。 That will tell you more readily where the memory is being used. 这样可以更轻松地告诉您内存的使用位置。 As it is, I can't see where the memory is used in that picture (then again - old eyes - when I enlarge it, it gets too blurry). 照原样,我看不到该图片在哪里使用了内存(然后,再次出现-旧眼睛-当我放大它时,它变得太模糊了)。

If you think it has to do with core data, why are you not running the core data instruments? 如果您认为它与核心数据有关,那么为什么不运行核心数据工具呢?

On to some diagnostic assistance. 继续提供一些诊断帮助。

Is your new MOC connected directly to the PSC or does it have a parent MOC. 您的新MOC是直接连接到PSC还是具有父MOC。 If it has a parent MOC, then the saves are just shoved into the parent MOC, and will stay in memory until the saves are persisted to the database. 如果它具有父MOC,则将保存内容仅推送到父MOC中,并将保留在内存中,直到保存内容保存到数据库中为止。

How many items are in your mediaSet? 您的mediaSet中有多少个项目? It's possible to have a lot of those, which could chew up memory. 可能有很多这样的东西,它们可能会消耗内存。

What parameters have you applied to the FetchRequest and the MOCs? 您已将哪些参数应用于FetchRequest和MOC? Based on those options, the MOCs could be retaining objects. 基于这些选项,MOC可以保留对象。 A way to check this is to log the counts of the retained/inserted/deleted/etc sets for each MOC. 一种检查方法是记录每个MOC的保留/插入/删除/等集的计数。 By logging those, you can see if either MOC is holding onto stuff you don't think it should be. 通过记录这些内容,您可以查看MOC是否正在保留您认为不应该的内容。

Then you can know if you need to refresh/reset your MOC. 然后,您可以知道是否需要刷新/重置MOC。

You could cheat, and call [moc reset] after saving, but it would be nice to see the numbers before/after doing that so you can convince yourself where the memory is. 您可以作弊,然后在保存后调用[moc reset] ,但是最好能在执行前后查看这些数字,以便使自己确信内存在哪里。

Do more debugging. 进行更多调试。 Give yourself more information so you can make good decisions... and it will give us better information to assist you as well. 给自己更多的信息,以便您可以做出明智的决定……这也将为我们提供更好的信息,以帮助您。

EDIT 编辑

Oooops. Oooops。 I removed the comments about possibly not being too much memory. 我删除了有关可能内存不足的注释。 My old eyes did me no favors looking at the tiny print on that image. 我的老眼睛让我看不到那幅图像上的小字。

EDIT 编辑

Thanks. 谢谢。 How do i log the counts of the retained/inserted/deleted sets for each MOC? 如何记录每个MOC的保留/插入/删除集的计数? – Andrew - 安德鲁

The MOC has several properties ( registeredObjects , insertedObjects , deletedObjects , updatedObjects ) that provide a set of objects matching those categories. 的MOC有几种特性( registeredObjectsinsertedObjectsdeletedObjectsupdatedObjects提供一组匹配这些类别的对象)。 Simply NSLog the count of objects in each category. 只需NSLog每个类别中的对象数。 You can see, for each MOC, how many objects the MOC is keeping track of over time. 对于每个MOC,您可以看到MOC随时间跟踪的对象数。

Also, enable the core data instruments. 另外,启用核心数据工具。 They are really informative. 他们确实提供了很多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM