2011-08-24 120 views
0

我面临分配对象的潜在泄漏。那么如何在循环中释放我的自定义类对象。下面附上我的代码。对象的潜在泄漏

- (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:用户名withEmail:USEREMAIL withPhone:PHONENUM]自动释放];所以我的应用程序崩溃了。所以我发布如果检查,但建立和分析显示它作为一个警告。

+0

呃,你有在任何地方有'init'调用吗? – jtbandes

+0

您需要发布'getProfileInfo:withEmail:withPhone:'的代码。 – Yuji

+0

正如你总是从这个ProfileClass * profile = nil;下面的代码将永远不会执行如果(profile) [profile release]; – Saran

回答

1

您也可以自动释放这样的:

返回[配置文件自动释放]

并保留ProfileClass在要用它的对象,

EX- ProfileClass * objProfile = [[数据库getUserProfile]保留];

并在您使用它时释放objProfile。

+0

但不是它与我的返回相同[[profile autorelease] retain]; ?? – user366584

+0

不,它不一样,因为如果你保留任何意味着你是该对象的所有者的对象。只有你可以发布它,所以你不能在其他课堂上发布它。 –

0

你为什么不这样做:

return [profile autorelease]; 

而且没有必要的

if (profile) 

检查。只需release无条件。如果profile为零,则不会有任何负面影响。


FWIW:我不太明白你的getProfile:etc...方法是做什么的。我认为这是一个初始化器,仅此而已(就像可可中的许多initXYZ:方法)。如果是这样,你应该把它叫做initWithUserName:email:phone:以符合约定。你可以发布该方法吗?

+0

我解决它作为返回[[任务autorelease]保留]; – user366584

+0

@ user366584只是b/c你的错误消失并不意味着你解决了它。在给出建议之前阅读内存管理。你用[[autorelease]保留]做了什么;是错的。您保留一个您正在自动释放的对象。背后的原因是什么?它接近了我,你只是盲目地解决问题,只需输入与内存管理相关的任何内容。 – Cyprian

+0

@ user366584:Cyprian是对的。 “它有效”并不意味着你所做的是正确的。在这种情况下,它没有任何意义。什么是'使命'? –

0

使用数组,你可以调用此方法

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

你的方法:- (ProfileClass *) getUserProfile不是一个实例方法或副本,应该返回一个自动发布的对象。但是你应该在最后一行做到这一点,因为你有一个if/else结构,并且如果你只是在线上自动释放它,它不会在if语句失败并转到其他语句时自动释放。因此,只要做到这一点:

return [profile autorelease]; 
+0

FWIW是同一个实例变量,它是一个实例方法,因为它在一个分配的实例上运行。这可能只是一个名称错误的初始值设定项。 –

+0

@Cyprian它崩溃了,所以这就是为什么我在上面的评论中提出了一个解决方案,但它不是正确的内存管理 – user366584