утечка памяти coredata - PullRequest
       2

утечка памяти coredata

0 голосов
/ 22 сентября 2009

У меня есть статический класс CoreDataHelper, который состоит из 2 статических методов. Я запустил свой проект через Clang и не обнаружил каких-либо утечек, однако прогон через Instruments показывает утечку, которая выглядит как связанная с CoreData. У меня есть базовые знания по управлению памятью в target-c, и я считаю, что я следую правилам. Тем не менее, я также думаю, что, скорее всего, что-то не так с моим кодом, а не ошибка в стеке CoreData от Apple. Я работаю на последней версии, Snow Leopard, iPhone SDK 3.1, XCode 3.2.

stack trace:

  17 UIKit     528 Bytes  -[UIApplication _run]

  16 UIKit      64 Bytes  -[UIApplication sendEvent:]

  15 UIKit      64 Bytes  -[UIApplication handleEvent:withNewEvent:]

  14 UIKit      64 Bytes  -[UIApplication _runWithURL:sourceBundleID:]

  13 UIKit      16 Bytes  -[UIApplication _performInitializationWithURL:sourceBundleID:]

  12 helm      16 Bytes  -[helmAppDelegate applicationDidFinishLaunching:] Classes/helmAppDelegate.m:113

  11 helm      16 Bytes  +[CoreDataHelper entityWithUIDexists:::] Classes/CoreDataHelper.m:50

  10 helm      16 Bytes  +[CoreDataHelper searchObjectsInContextCopy:::::] Classes/CoreDataHelper.m:39

   9 CoreData      16 Bytes  -[NSManagedObjectContext executeFetchRequest:error:]

   8 CoreData      16 Bytes  -[NSPersistentStoreCoordinator(_NSInternalMethods) executeRequest:withContext:]

   7 CoreData      16 Bytes  -[NSSQLCore executeRequest:withContext:]

   6 CoreData      16 Bytes  -[NSSQLiteConnection connect]

   5 CoreData      16 Bytes  -[NSSQLConnection createSchema]

   4 CoreData      16 Bytes  -[NSSQLConnection createTablesForEntities:]

   3 CoreData      16 Bytes  -[NSSQLConnection createTableForEntity:]

   2 CoreData      16 Bytes  -[NSSQLAdapter newCreateTableStatementForEntity:]

   1 Foundation      16 Bytes  -[NSCFString appendFormat:]

   0 CoreFoundation      16 Bytes  -[NSObject respondsToSelector:]

AppDelegate:

BOOL b=[CoreDataHelper entityWithUIDexists:@"AddressBook" :context :[NSNumber numberWithInt:1]];

CoreDataHelper:

+(NSMutableArray *) searchObjectsInContextCopy: (NSString*) entityName : (NSManagedObjectContext *) managedObjectContext : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending 
{
    NSLog(@"searchObjectsInContext");
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
    [request setEntity:entity]; 

    // If a predicate was passed, pass it to the query
    if(predicate != nil)
    {
        [request setPredicate:predicate];
    }

    // If a sort key was passed, use it for sorting.
    if(sortKey != nil)
    {
        //NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending selector: @selector(caseInsensitiveCompare:)];
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending selector: @selector(caseInsensitiveCompare:)];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
        [request setSortDescriptors:sortDescriptors];
        [sortDescriptors release];
        [sortDescriptor release];
    }

    NSError *error;

    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

    [request release];

    return mutableFetchResults;
}


+(BOOL) entityWithUIDexists: (NSString *) entityName : (NSManagedObjectContext *) managedObjectContext : (NSNumber *) uid {
    BOOL b;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(uid == %@)", uid];
    NSMutableArray *ary=[self searchObjectsInContextCopy: entityName : managedObjectContext : predicate : nil : YES]; 
    if(ary==nil) {
        b=NO;
    } else {
        b=[ary count] >0 ? YES :NO;
    }

    [ary release];
    return b;
}

Ответы [ 2 ]

1 голос
/ 22 сентября 2009

Глядя на ваш исходный код, я заметил две вещи. Во-первых, неправильно инициализировать запрос на выборку без дескрипторов сортировки. Цитирование из примечаний к выпуску SDK 3.1:

"NSFetchedResultsController больше не падает, когда запрос на выборку не имеет дескрипторов сортировки. Инициализировать NSFetchedResultsController без дескрипторов сортировки по-прежнему недопустимо, но теперь вызывается правильное исключение"

Следовательно, вы всегда должны инициализировать NSFetchedResultsController с дескрипторами сортировки. Вторая вещь связана с вашей утечкой. ExecuteFetchRequest: метод возвращает автоматически освобожденный NSArray. Вы используете метод mutableCopy и поэтому возвращаете объект, который был сохранен mutableCopy. Это в основном означает, что вы несете ответственность за освобождение возвращенного объекта. Снова цитируем документацию по методу mutableCopy:

"Если вы используете управляемую память (не сборщик мусора), этот метод сохраняет новый объект до его возвращения. Однако инициатор метода отвечает за освобождение возвращенного объекта."

0 голосов
/ 23 сентября 2009

Хорошо, я обнаружил кое-что интересное. Дескриптор нулевого сорта не вызывал утечку, он все еще был там, но, возможно, я слишком рано остановил детектор утечки. Вот метод с утечкой. Когда я закомментирую марку прагмы, 16-байтовая утечка не отображается в инструментах. Почему наличие метки-прагмы в методе приводит к утечке в 16 байт?

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSString *databaseFilePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Locations.sqlite"];


    NSFileManager *fileManager = [NSFileManager defaultManager];

    if([fileManager fileExistsAtPath:databaseFilePath])
    {
# pragma mark - flag to delete file
        NSError *fMerror;
        if (![fileManager removeItemAtPath:databaseFilePath error:&fMerror]) {
           NSLog(@"persistentStoreCoordinator error %@, %@", fMerror, [fMerror userInfo]);    
        }

    }


    NSURL *storeUrl = [NSURL fileURLWithPath: databaseFilePath];

    NSError *error;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
        NSLog(@"persistentStoreCoordinator error %@, %@", error, [error userInfo]);    }    

    return persistentStoreCoordinator;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...