Потенциальная утечка объекта - PullRequest
0 голосов
/ 24 августа 2011

Я столкнулся с потенциальной утечкой выделенного объекта.Итак, как я могу выпустить свой собственный объект класса в цикле.Ниже я прилагаю свой код ниже.

- (ProfileClass *) getUserProfile

{

NSString *query = [NSString stringWithFormat:@"SELECT * FROM Profile"];
NSLog(@"query %@",query);

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"MOFAdb.sqlite"];
ProfileClass *profile = nil;
// Open the database. The database was prepared outside the application.
if(sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{

    sqlite3_stmt *Statement1;
    //int i=0;
    if (sqlite3_prepare_v2(database, [query UTF8String], -1, &Statement1, NULL) == SQLITE_OK) {

        //int returnValue = sqlite3_prepare_v2(database, sql, -1, &Statement1, NULL);
        if (sqlite3_step(Statement1) == SQLITE_ROW) {
            // The second parameter indicates the column index into the result set.

            NSString *userName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 0)];
            NSString *userEmail = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 1)];
            NSString *phoneNum = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 2)];
            //int phone = sqlite3_column_int(Statement1, 2);
            //NSLog(@"%d",phone);

            //RecipeClass *rc = [[RecipeClass alloc] getRecipe:recipeName withRecipeIng:recipeIng withRecipeInst:recipeInstru withRecipeTips:recipeTips withRecipeDesc:recipeDesc];

            if (profile) 
                [profile release];

            profile = [[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum];

            //NSLog(@"%@",fact);
            //NSLog(@"%d",i);
            //i++;      

        }
    }

    //Release the select statement memory.
    sqlite3_finalize(Statement1);
    //}
}
else {
    // Even though the open failed, call close to properly clean up resources.
    sqlite3_close(database);
    NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
    // Additional error handling, as appropriate...
}

return profile; 

}

Если я автоматически выпускаю свой профиль = [[[ProfileClass alloc] getProfileInfo: userName withEmail: userEmail withPhone: phoneNum] автоматический выпуск];поэтому мое приложение вылетает позже.Так что я отпускаю, если проверка, но сборка и анализ показывает это как предупреждение.

Ответы [ 4 ]

1 голос
/ 24 августа 2011

Вы также можете сделать авто-релиз следующим образом:

return [автопродание профиля];

и сохраните объект ProfileClass, где вы его использовали,

Ex- ProfileClass * objProfile = [[база данных getUserProfile] сохранить];

и освободите objProfile, когда вы его использовали.

0 голосов
/ 24 августа 2011

используя массив, вы можете решить эту проблему перед вызовом этого метода

NSMutableArray *ProfileArray=[[NSMutableArray alloc] initWithArray:[ClassObj getUserProfile]];
ProfileClass *profileObj=[[ProfileArray objectAtIndex:0] retain];
[ProfileArray release];
// now you can use profile object anywhere... I hope memory issue is also solved



- (NSMutableArray *) getUserProfile

{
    NSMutableArray *array=[[NSMutableArray alloc] init];

NSString *query = [NSString stringWithFormat:@"SELECT * FROM Profile"];
NSLog(@"query %@",query);

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"MOFAdb.sqlite"];
ProfileClass *profile = nil;
// Open the database. The database was prepared outside the application.
if(sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{

    sqlite3_stmt *Statement1;
    //int i=0;
    if (sqlite3_prepare_v2(database, [query UTF8String], -1, &Statement1, NULL) == SQLITE_OK) {

        //int returnValue = sqlite3_prepare_v2(database, sql, -1, &Statement1, NULL);
        if (sqlite3_step(Statement1) == SQLITE_ROW) {
            // The second parameter indicates the column index into the result set.

            NSString *userName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 0)];
            NSString *userEmail = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 1)];
            NSString *phoneNum = [NSString stringWithUTF8String:(char *)sqlite3_column_text(Statement1, 2)];
            //int phone = sqlite3_column_int(Statement1, 2);
            //NSLog(@"%d",phone);

            //RecipeClass *rc = [[RecipeClass alloc] getRecipe:recipeName withRecipeIng:recipeIng withRecipeInst:recipeInstru withRecipeTips:recipeTips withRecipeDesc:recipeDesc];

            if (profile) 
                [profile release];

            profile = [[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum];
       [array addObject:profile];
       [profile release];


        }
    }

    //Release the select statement memory.
    sqlite3_finalize(Statement1);
    //}
}
else {
    // Even though the open failed, call close to properly clean up resources.
    sqlite3_close(database);
    NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
    // Additional error handling, as appropriate...
}

return [array autorelease]; 

}

Надеюсь, это будет полезно для вас

0 голосов
/ 24 августа 2011

Ваш метод: - (ProfileClass *) getUserProfile не является методом экземпляра или копией, вы должны вернуть объект, который был автоматически освобожден. Но вы должны сделать это в последней строке, так как у вас есть структура if / else, и если вы только автоматически выпускаете ее в строке profile = [[[ProfileClass alloc] getProfileInfo:userName withEmail:userEmail withPhone:phoneNum] autorelease];, она не будет автоматически освобождена, если она не выполнит оператор if и перейдет к else. Так что просто сделайте это:

return [profile autorelease];
0 голосов
/ 24 августа 2011

Почему бы вам не сделать:

return [profile autorelease];

И нет необходимости в

if (profile)

проверка. Просто release безоговорочно. Если profile равно нулю, это не будет иметь никакого отрицательного эффекта.


FWIW: Я не совсем понимаю, что делает ваш метод getProfile:etc.... Я предполагаю, что это инициализатор и ничего более (как многие методы initXYZ: в Какао). Если это так, то вам, вероятно, следует назвать это initWithUserName:email:phone:, чтобы придерживаться соглашения. Не могли бы вы опубликовать метод?

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