【问题标题】:Problem in memory manegment?内存管理问题?
【发布时间】:2010-09-17 12:17:25
【问题描述】:

我正在开发一个应用程序,我在其中处理数据库操作。我在数据库类中写的方法如下。

-(NSMutableArray *)getData: (NSString *)dbPath{
    NSMutableArray *dataArray = [[NSMutableArray alloc] init];

    if(sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK){
        NSString *sqlQuery = [NSString stringWithFormat:@"SELECT empID, addText FROM Employee WHERE nameID = %@", nameID];
        sqlite3_stmt *selectstmt;
        if(sqlite3_prepare_v2(database, [sqlQuery UTF8String], -1, &selectstmt, NULL) == SQLITE_OK){

           while (sqlite3_step(selectstmt) == SQLITE_ROW){
                [dataArray addObject:[[NSMutableDictionary alloc] init]];

                [[dataArray lastObject] setObject:[NSString 
                                 stringWithFormat:@"%d", sqlite3_column_int(selectstmt, 0)] forKey:@"empID"];

                [[dataArray lastObject] setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)] forKey:@"addText"];
            }
        }

        sqlite3_finalize(selectstmt);
    }
    sqlite3_close(database);
    return dataArray;
}

上面的代码在模拟器上工作正常,但在设备上不行。 我也在追踪内存泄漏,我在上面的方法代码中发现了内存泄漏。但我无法解决那个内存泄漏。

现在我也发现了以下方法的内存泄漏。

  • (id)initWithString:(NSString *)str 属性:(NSDictionary *)属性

{ if ((self = [super init])) { _buffer = [str mutableCopy]; _attributes = [NSMutableArray arrayWithObjects:[ZAttributeRun attributeRunWithIndex:0 attributes:attributes], nil]; } 回归自我; }

_buffer = [str mutableCopy]; 附近的泄漏。并且泄漏跟踪使我在输出中不断增加 NSCFString 字符串分配。我如何维护它?

提前致谢。

【问题讨论】:

    标签: objective-c ipad


    【解决方案1】:

    您的泄漏是您没有释放dataArray 对象,也没有释放您在while 循环中创建的可变字典。考虑自动释放可变数组,并在将字典添加到数组后手动释放它们。

    至于为什么它在设备上“不起作用”,您需要更具体地了解发生了什么以及为什么这不是您所期望的。

    【讨论】:

    • @Graham Lee,谢谢。您是说 dataArray 释放应该是手动的。但是我们不能在 return 语句之前释放 dataArray。如果我们在 return 语句之前释放 dataArray,我们会从 dataArray 中丢失所有对象,对吗?
    • @rajb 其实我说过你应该自动释放dataArray,这样可以避免你提出的问题(这确实是正确的)。
    • @Graham Lee,Thanks.NSMutableArray *dataArray = [NSMutableArray array];这条线会自动释放对吗?
    • @Graham Lee,当我在设备上运行该应用程序时,它会在该应用程序崩溃后向我发出 3 次内存级别警告。
    • @RRB:也许你有不止一个泄漏。
    【解决方案2】:

    您的内部循环会泄漏 NSMutableDictionary 对象,因为您应该在添加到数组后 release 它们,即

    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    [dict setObject:[NSString  stringWithFormat:@"%d", sqlite3_column_int(selectstmt, 0)] forKey:@"empID"];
    [dict setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)] forKey:@"addText"];
    [dataArray addObject:dict];
    [dict release];
    

    此外,您的整个方法很可能应该通过命名约定返回一个自动释放的对象。不确定这是否是泄漏 - 取决于您如何调用该方法以及是否释放返回值。

    所以也许使用

    return [dataArray autorelease];
    

    【讨论】:

    • return[dataArray autorelease];我以前使用过的语句,但它不起作用。首先它显示员工数据,当我从员工表中检索另一行时,它会给出“_kill”错误。
    • 感谢.NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; [dict setObject:[NSString stringWithFormat:@"%d", sqlite3_column_int(selectstmt, 0)] forKey:@"empID"]; [dict setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)] forKey:@"addText"]; [dataArray addObject:dict]; [字典发布];上面的存根运行良好。
    【解决方案3】:

    乍一看,您有 2 个可能发生泄漏的地方:

    NSMutableArray *dataArray = [[NSMutableArray alloc] init];
    ...
    return dataArray;
    

    调用者方法负责释放从您的方法返回的数组 - 检查是否这样做。

    此外,您的方法名称与 obj-c 指南不一致 - 他们建议返回非自动释放对象的方法(因此调用者负责释放它们)应该在其名称中包含 create、alloc、copy。所以最好从这个方法返回自动释放的数组(return [dataArray autorelease];,让调用者决定是否需要保留数组。

    第二名是

    [dataArray addObject:[[NSMutableDictionary alloc] init]];
    

    它正在泄漏字典对象,您应该只写

    [dataArray addObject:[NSMutableDictionary dictionary]];
    

    【讨论】:

      【解决方案4】:

      您的方法包含两个对+alloc 的调用,它们没有对-release-autorelease 的相应调用。

      NSMutableArray *dataArray = [[NSMutableArray alloc] init];
      ...
      [dataArray addObject:[[NSMutableDictionary alloc] init]];
      

      您可以像这样重写这些行以消除泄漏:

      NSMutableArray *dataArray = [NSMutableArray array];
      ...
      [dataArray addObject:[NSMutableDictionary dictionary]];
      

      【讨论】:

      • 谢谢,请解释一下 NSMutableArray *dataArray = [NSMutableArray array]; 之间的区别和 NSMutableArray *dataArray = [[NSMutableArray alloc] init];? 的声明
      • NSMutableArray *dataArray = [NSMutableArray 数组];声明现在运行良好。
      • +array 方法返回一个通过调用[[[NSMutableArray alloc] init] autorelease] 创建的对象(至少在概念上)。熟悉内存管理的最佳方法是阅读 Apple 出色的内存管理指南:developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/…
      猜你喜欢
      • 1970-01-01
      • 2012-07-23
      • 2011-01-07
      • 2016-10-20
      • 2011-04-11
      • 2013-09-01
      相关资源
      最近更新 更多