2011-04-16 39 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];很好。