2011-04-16 2 views
0

В моем приложении у меня возникли утечки памяти в NSMutableArray, NSArray и NSString.Утечка памяти в NSMutableArray, NSArray, NSString в iPhone SDK

Вот код.

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) во втором цикле.

И subArray и langArray - мои глобальные массивы.

Если я удалю mutableCopy от NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; и NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];, то subArray и langArray не сохраняют значения.

Как избежать утечки памяти в этом коде?

+0

Что '-returnExecuteQuery:' делать? Возвращает ли он принадлежащий или не принадлежащий ему объект? Подходит ли в его контракте что-либо о допустимости возвращаемого значения для нескольких вызовов? –

+0

Вы выпускаете tempArray? где? Кроме того, попробуйте освободить subArray1 и newArray (вместо этого их авторекламу) после addObjectsFromArray. – Sefran2

+0

@Fran: Я попытался освободить оба массива после основного цикла, но он дает мне ошибку EXEC_BAD_ACCESS для subArray и langArray. – Meghan

ответ

1

Прошу прощения, в приведенном выше коде вы создаете два множества объектов, принадлежащих к пулу автоопределений, здесь есть одна версия, где я пытался обрабатывать выпуск этих строковых переменных.

Во-вторых, утечка detail связана с тем, что вы являетесь de-referencing это много раз в вашем коде. А для 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]; 

UPDATE 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]; [detail release]; 'after for loop, это показывает утечку в' detail'. subArray1 и newArray по-прежнему обнаруживают утечку в Инструментах. – Meghan

+0

См. Выше код, а также ответьте на комментарии в коде, чтобы сценарий мог быть более четким. спасибо – Ravin

+0

В первом и втором комментариях: Массивы являются авторекламой. и Третий комментарий: Я проверяю условие для нулевых или пустых значений. Если checknull не пуст или null, он должен добавить строку с деталями '\ n'. Чтобы я мог отображать его в тексте детали ячейки. – Meghan

1

Не уверен, что вызывает утечку памяти, но это может помочь. Это более прямой способ копирования массивов, и может привести к избежание утечки:

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

В основном это делает одноуровневый глубокую копию массива, возвращаемого returnExecuteQuery. Вы можете прочитать об этом более подробно в Collections Programming Topics.

Я не уверен, как работает mutableCopy, и это может иметь какое-то отношение к утечке. Если он копирует объекты в старом массиве &, то добавляет их в новый массив, они могут вводить массив с сохранением количества 2 (1 из копии и 1 из добавляемых в массив). Это не делает что он должен работать таким образом. Но если это произойдет, это может объяснить утечку.

+0

@ salo.dm: Спасибо за ваш Ответить. Это помогает мне в некоторых случаях. Он по-прежнему показывает утечку в 'detail',' subArray1' и 'newArray'. – Meghan

+0

Если вы используете этот код, вам не понадобится newArray. Вы можете удалить всю строку, ссылающуюся на newArray. Аналогично, вы можете покончить с subArray1, заменив 2-й и 3-й строки в вашем коде следующим образом: NSArray * subArray = [[NSArray alloc] initWithArray: [self returnExecuteQuery: subQuery] copyItems: YES]; –

+0

dm: каждый раз, когда этот метод вызывает это, он добавляет новый buch данных в langArray. так что это не поможет мне – Meghan

0

Вы можете начать с отпускания своего tempArray после его завершения (после циклов).

Часто утечки более высоких уровней скрыты в потоке более низких уровней (т.е. утечка контейнера также вызывает утечку всего содержимого), что может иметь место для вашей строки.

Использование mutableCopy] autorelease]; в порядке.

Смежные вопросы