указатель утечки памяти iPhone - PullRequest
0 голосов
/ 24 июля 2010

другой вопрос управления памятью: Я спрашивал об этом раньше, но не получил ответа:

Вопрос в том, приведет ли утечка к следующему или это нормально?

NSArray *txtArray = [NSArray array];

NSString *aTxtFieldTxt = [[NSString alloc]initWithString:aTxtField.text];
aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];


NSMutableString *aTxt = [[NSMutableString alloc]initWithString:aTxtFieldTxt];
[aTxtFieldTxt release];


txtArray = [aTxt componentsSeparatedByString:@" "];

aTxt = [[txtArray objectAtIndex:0] retain];


for(int i = 1; i < [txtArray count]; i++){

   [aTxt appendString:@"+"];
   [aTxt appendString:[[txtArray objectAtIndex:i]retain]];
}

Это часть функции. И я не уверен, что присвоение aTxt = [[txtArray objectAtIndex:0] retain]; вызывает утечку, потому что это указатель, который изначально указывает на

NSMutableString *aTxt = [[NSMutableString alloc]initWithString:aTxtFieldTxt];
[aTxtFieldTxt release];

Как мне сделать это правильно. Должен ли я использовать другой указатель? Может кто-нибудь объяснить, пожалуйста, эту проблему?

Большое спасибо!

Ответы [ 4 ]

1 голос
/ 24 июля 2010

Много и много проблем с этим кодом.

//
// Don't do this.  Just declare the txtArray
//
NSArray *txtArray /* = [NSArray array]*/;

//
// You need to auto release after init in this case.
//
NSString *aTxtFieldTxt = [[[NSString alloc]initWithString:[aTxtField text]] autorelease]; 

//
// You are reassigning the aTxtFieldTxt and the new value is returned autoreleased.
//
aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet  whitespaceAndNewlineCharacterSet]];

//
// Again, autorelease after init
//
NSMutableString *aTxt = [[[NSMutableString alloc]initWithString:aTxtFieldTxt] autorelease]; 

//
// You never alloced this instance so it needs no release.
//
 /*[aTxtFieldTxt release]; */

//
// This array is returned autoreleased
//
txtArray = [aTxt componentsSeparatedByString:@" "];

//
// No need to retain here.  Just get the object
//
aTxt = /*[*/[txtArray objectAtIndex:0]/* retain]*/;

for(int i = 1; i < [txtArray count]; i++)
{
    [aTxt appendString:@"+"]; 
    [aTxt appendString:[[txtArray objectAtIndex:i]retain]]; 
}

Я обнаружил, что если вы сохраняете / выпускаете за пределами процедур accessors / base int / dealloc, вы делаете что-то не так. Для каждого alloc вы должны иметь сбалансированный выпуск / сохранение для этого экземпляра объекта. Если вы переназначите переменную, вы потеряете ссылку на нее.

Это быстрый ответ на то, как я написал бы этот код:

NSArray         *txtArray;
NSString        *aTxtFieldTxt = [NSString stringWithString:[aTxtField text]];
NSMutableString *aTxt;

aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
aTxt         = [NSMutableString stringWithString:aTxtFieldTxt]; 
txtArray     = [aTxt componentsSeparatedByString:@" "];

aTxt = [NSMutableString stringWithString:[txtArray objectAtIndex:0]];
for(int i = 1; i < [txtArray count]; i++)
{
    [aTxt appendString:@"+"]; 
    [aTxt appendString:[[txtArray objectAtIndex:i]retain]]; 
}
1 голос
/ 24 июля 2010

Попробуйте запустить приложение с утечками.Посмотрите, не вызывает ли это утечку. Утечки - это инструмент в Инструменты .

0 голосов
/ 24 июля 2010

Как отмечали другие, этот код просачивается повсюду.

Действительно хорошим способом найти тех, кто даже не запускает ваш код, является статический анализатор !

Используйте Построить и проанализировать из меню Построение, и оно покажет вам, какие утечки и почему, с полными путями кода.

0 голосов
/ 24 июля 2010
aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

Это приведет к потере исходной ссылки на aTxtFieldTxt (таким образом, к утечке). Хуже того, удобная функция вернет объект со счетом сохранения 0, поэтому -release позже приведет к аварийному завершению программы.

Лучше записать как

// don't stuff everything into a single line.
NSCharacterSet* charsToTrim = [NSCharacterSet whitespaceAndNewlineCharacterSet];
// there's no need to create a copy of the string.
NSString* aTxtFieldTxt = [aTxtField.text stringByTrimmingCharactersInSet:charsToTrim];

// don't release stuff with retain count 0.

// you just want to replace all ' ' by '+' right? there's a method for that.
NSString* aTxt = [aTxtFieldTxt stringByReplacingOccurrencesOfString:@" "
                                                         withString:@"+"];

Редактировать: если вам нужно заменить несколько пробелов на один +, вам нужно проанализировать строку, например,

NSCharacterSet* charsToTrim = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSString* aTxtFieldTxt = [aTxtField.text stringByTrimmingCharactersInSet:charsToTrim];

NSScanner* scanner = [NSScanner scannerWithString:aTxtFieldTxt];
[scanner setCharactersToBeSkipped:nil];
NSMutableString* aTxt = [NSMutableString string];
NSCharacterSet* whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
while (![scanner isAtEnd]) {
   NSString* res;
   [scanner scanUpToCharactersFromSet:whitespaceSet intoString:&res];
   [aTxt appendString:res];
   if ([scanner scanCharactersFromSet:whitespaceSet intoString:NULL])
      [aTxt appendString:@"+"];
}
...