2011-04-16 68 views
0

在我的应用程序中,我在NSMutableArray,NSArray和NSString中得到了内存泄漏。iPhone SDK中的NSMutableArray,NSArray,NSString中的内存泄漏

这是代码。

NSString *subQuery = [NSString stringWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName]; 
    NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];   
    [subArray addObjectsFromArray:subArray1]; 

    NSString *columnQuery = [NSString stringWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName]; 
    NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; 
    [langArray addObjectsFromArray:newArray]; 

    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 

    for (int i=0; i<[newArray count]; i++) { 
     NSString *cellText = [[newArray objectAtIndex:i] valueForKey:[NSString stringWithFormat:@"%@",lblshortName.text]]; 

     if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""]) { 
      NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 

      [tempArray addObject:[NSString stringWithFormat:@"%@ : %@",lblshortName.text, decodedString3]]; 
     } 
     else { 
      [tempArray addObject:@"<empty>"]; 
     } 

     NSString *detail = @"_________________"; 

     for (int j=0; j<[lableNameArray count]; j++) { 

      NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:[NSString stringWithFormat:@"%@",[lableNameArray objectAtIndex:j]]]; 

      if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       detail = [NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]; 
      }    
     } 
     [detailTextArray addObject:detail]; 

    } 

当我在仪器运行我在第二行

-subArray1了泄漏。

-detail(NSString)for second for loop。

而subArray和langArray是我的全局数组。

如果我从NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];删除mutableCopy,则subArray和langArray不会保留值。

如何避免此代码中的内存泄漏?

+0

是什么'-returnExecuteQuery:'怎么办?它是返回一个拥有的还是非拥有的对象?其合同是否会说明多次调用的返回值有效性? – 2011-04-16 11:12:20

+0

你释放tempArray吗?哪里?此外,尝试在addObjectsFromArray之后释放subArray1和newArray(而不是自动释放它们)。 – Sefran2 2011-04-16 12:05:26

+0

@Fran:我试图在main for循环之后释放两个数组,但它给了我subECray和langArray的EXEC_BAD_ACCESS错误。 – Meghan 2011-04-16 12:43:08

回答

1

Olease试试这个,在上面的代码中,你正在创建属于自动释放池的两个很多对象,这里是我试图处理这些字符串变量释放的一个版本。

其次,这是泄漏detail是因为你多次在你的代码中引用。而对于subArray1请参见注释

NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName]; 
    // please make returnExecuteQuery's returned array autorelease if it is not. 
    NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ; 
    [subArray addObjectsFromArray:subArray1]; 

    [subQuery release]; 
    NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName]; 
    NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ; 
    [langArray addObjectsFromArray:newArray]; 
    [columnQuery relese]; 
    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 

    for (int i=0; i<[newArray count]; i++) { 
     NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:@"%@",lblshortName.text]]; 


     NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey]; 
     [tempKey release]; 

     if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""]) { 
      NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
      NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:@"%@ : %@",lblshortName.text, decodedString3]]; 

      [tempArray addObject:tempString]; 
      [tempString release]; 
     } 
     else { 
      [tempArray addObject:@"<empty>"]; 
     } 

     NSMutableString *detail = nil; 

     for (int j=0; j<[lableNameArray count]; j++) 
     { 
      detail = [[ NSMutableString alloc]initWithString:@"_________________"]; 
      NSMutableString *key = [[NSMutableString alloc]initWithFormat:@"%@",[lableNameArray objectAtIndex:j]]; 
      NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; 
      [key release]; 

      if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       [detail setString:[NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]]; 
      } 
       [detailTextArray addObject:detail]; 
       [detail release];    
     } 


    } 
    [subArray1 release]; 
    [newArray release]; 

UPDATE:请务必阅读代码中的注释和回信,这样的东西可以改进。

NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName]; 
    //*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not. 
    NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ; 
    [subArray addObjectsFromArray:subArray1]; 

    [subQuery release]; 
    NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName]; 
    //*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not. 
    NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ; 
    [langArray addObjectsFromArray:newArray]; 
    [columnQuery relese]; 
    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 

    for (int i=0; i<[newArray count]; i++) { 
     NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:@"%@",lblshortName.text]]; 


     NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey]; 
     [tempKey release]; 

     if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""]) { 
      NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
      NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:@"%@ : %@",lblshortName.text, decodedString3]]; 

      [tempArray addObject:tempString]; 
      [tempString release]; 
     } 
     else { 
      [tempArray addObject:@"<empty>"]; 
     } 

     NSMutableString *detail = [[ NSMutableString alloc]initWithString:@"_________________"]; 

     for (int j=0; j<[lableNameArray count]; j++) 
     { 

      NSMutableString *key = [[NSMutableString alloc]initWithFormat:@"%@",[lableNameArray objectAtIndex:j]]; 
      NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; //also here if you note you are using subArray1 not subArray? 
      [key release]; 

      if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       [detail setString:[NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]]; 
       break;//I am not sure why you are checking this condition but assume that you want to get NOT NULL VALUE and add it to array? 
      } 

     } 
     [detailTextArray addObject:detail]; 
     [detail release];    

    } 
    [subArray1 release]; 
    [newArray release]; 

更新2:

if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0) 
      { 
       NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]]; 
       [detail appendFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]]; 

      } 

感谢,

+0

感谢您的代码,但仍然存在一些问题,我想添加'[detailTextArray addObject:detail]; [详细发布];'for循环之后,它显示'detail'中的泄漏。在Instrument中,subArray1和newArray仍然显示泄漏。 – Meghan 2011-04-18 10:49:43

+0

请参阅上面的代码,并回答代码中的注释,以便场景更清晰。谢谢 – Ravin 2011-04-18 16:53:24

+0

在第一和第二个评论:数组autorelease。和第三条评论:我正在检查空值或空值的条件。如果checknull不为空或为空,它应该在'\ n'中附加详细的字符串。这样我可以在单元格的细节文本中显示它。 – Meghan 2011-04-25 03:23:12

1

不知道是什么导致内存泄漏,但这可能有所帮助。这是复制阵列的更直接的方式,并且可能导致避免泄漏:

NSArray *langArray =[[NSArray alloc] initWithArray: [self returnExecuteQuery:columnQuery] copyItems: YES]; 

这基本上使得由returnExecuteQuery返回的数组的一个层次的深层副本。您可以在Collections Programming Topics中详细了解它。

我不确定mutableCopy是如何工作的,这可能与泄漏有关。如果它复制旧数组012中的对象,然后将它们添加到新数组中,则它们可以保留计数为2(从副本中为1,并将1添加到数组中)输入数组。很重要的是它应该以这种方式工作。但是,如果确实如此,那可能会导致泄漏。

+0

@ salo.dm:谢谢你的回复。它在某些情况下帮助我。它仍然在'detail','subArray1'和'newArray'中显示泄漏。 – Meghan 2011-04-18 10:51:16

+0

如果你使用这段代码,你将不需要newArray。您可以删除引用newArray的整行。同样,你可以通过用下面的代码替换第二行和第三行来取消subArray1:NSArray * subArray = [[NSArray alloc] initWithArray:[self returnExecuteQuery:subQuery] copyItems:YES]; – 2011-04-18 11:16:17

+0

dm:每当这个方法调用它时,都会在langArray中添加新的buch数据。所以这不会帮助我 – Meghan 2011-04-18 15:53:13

0

你可以从释放你的tempArray开始(在循环之后)。

通常,较高级别的泄漏隐藏在较低级别泄漏(即容器泄漏导致其所有内容也被泄漏)中,这可能是您的字符串的情况。

使用mutableCopy] autorelease];很好。