Неизвестная утечка памяти в iPhone - PullRequest
1 голос
/ 04 апреля 2011

В настоящее время я создаю приложение для iPhone и не могу понять, почему в инструменте Leaks Instrument появляется утечка памяти.

Вот код, и я добавил комментарии к двум местам, где это происходит.

NSString *pathname = [[NSBundle mainBundle]  pathForResource:self.toUseFile ofType:@"txt" inDirectory:@"/"];
    //Line below causes a leak
    self.rawCrayons = [[NSString stringWithContentsOfFile:pathname encoding:NSUTF8StringEncoding error:nil] componentsSeparatedByString:@"\n"];

    self.sectionArray = [NSMutableArray array];
    for (int i = 0; i < 26; i++) [self.sectionArray addObject:[NSMutableArray array]];


    for(int i=0; i<self.rawCrayons.count; i++)
    {
        self.string = [self.rawCrayons objectAtIndex:i];
        NSUInteger firstLetter = [ALPHA rangeOfString:[string substringToIndex:1]].location;
        if (firstLetter != NSNotFound)
        {
            NSInteger audio = AUDIONUM(self.string);
            NSInteger pictures = PICTURESNUM(self.string);
            NSInteger videos = VIDEOSNUM(self.string);
            //Line below causes a leak
            [[self.sectionArray objectAtIndex:firstLetter] addObject:[[Term alloc] initToCall:NAME(self.string):audio:pictures:videos]];
        }

        [self.string release];
    }

Заранее спасибо!

Редактировать

Вот мои объявления о недвижимости.

@property (nonatomic, retain) NSArray *filteredArray;
@property (nonatomic, retain) NSMutableArray *sectionArray;
@property (nonatomic, retain) UISearchBar *searchBar;
@property (nonatomic, retain) UISearchDisplayController *searchDC;
@property (nonatomic, retain) NSString *toUseFile;
@property (nonatomic, retain) NSArray *rawCrayons;
@property (nonatomic, retain) NSString *string;

@property (nonatomic, retain) TermViewController *childController;

Вот утечки, которые происходят после исправлений Ника Уивера. Memory Leaks

Вот расширенная версия одного из NSCFString. Memory Leaks in Depth

И еще одно изображение. Another one in depth

Изображение с ответственным абонентом: Responsible Caller

Кроме того, поскольку это может быть полезно, вот свойства для термина:

@property (nonatomic, retain) NSString *name;
@property (nonatomic) NSInteger numberAudio;
@property (nonatomic) NSInteger numberPictures;
@property (nonatomic) NSInteger numberVideos;

И реализация:

@implementation Term

@synthesize name, numberAudio, numberPictures, numberVideos;

- (Term*)initToCall:(NSString*) toSetName:(NSInteger) audio:(NSInteger) pictures:(NSInteger) videos
{
    self.name = [toSetName retain];
    self.numberAudio = audio;
    self.numberPictures = pictures;
    self.numberVideos = videos;

    return self;
}

- (NSString*)getName
{
    return [[name retain] autorelease];
}

-(void)dealloc
{
    [name release];
    [super dealloc];
}

@end

Ответы [ 3 ]

2 голосов
/ 04 апреля 2011

Хорошо, попробуйте эту измененную версию Temp.Я удалил геттер, потому что у вас уже есть синтезатор.Вы не можете использовать метод получения, как это, для имени:

term.name

Проблема заключалась в том, как вы устанавливаете имя: вы хотите получить копию имени и установить ее с помощью синтезированного сеттера без вызова сохранения, и это должно помочь,Конечно, вы могли бы установить его с сохраненным свойством name, но вы должны были бы опустить retain, как это self.name = toSetName;.Сеттер сохранит его для вас.

@property (nonatomic, copy) NSString *name;
@property (nonatomic) NSInteger numberAudio;
@property (nonatomic) NSInteger numberPictures;
@property (nonatomic) NSInteger numberVideos;


@implementation Term

@synthesize name, numberAudio, numberPictures, numberVideos;

- (Term*)initToCall:(NSString*) toSetName:(NSInteger) audio:(NSInteger) pictures:(NSInteger) videos
{
    self.name = toSetName;
    self.numberAudio = audio;
    self.numberPictures = pictures;
    self.numberVideos = videos;

    return self;
}

-(void)dealloc
{
    [name release];
    [super dealloc];
}

Добавление объекта в массив сохранит экземпляр, поэтому сохранение равно 2, потому что вы вызываете

[[Term alloc]initToCall ..

Сделайте что-то вроде

Term *term = [[Term alloc] initToCall..];

[theArray addObject:term];

[term release];

1.Видите стрелку в первой строке в столбце адреса?Нажми! enter image description here

2.После нажатия:) enter image description here

1 голос
/ 04 апреля 2011

Изменение:

[[self.sectionArray objectAtIndex:firstLetter] addObject:[[Term alloc] initToCall:NAME(self.string):audio:pictures:videos]];

до:

Term *tempTerm = [[Term alloc] initToCall:NAME(self.string):audio:pictures:videos];
[[self.sectionArray objectAtIndex:firstLetter] addObject:tempTerm];
[tempTerm release];

Распределяя объект, вы отвечаете за его освобождение.

1 голос
/ 04 апреля 2011

Сложно сказать, почему первая утечка, потому что мы не знаем, как объявлена ​​собственность.Это сохранить?копировать?назначить?что?

Последний из них довольно понятен, хотя вы получаете право собственности на объект Term, а не освобождаете его при добавлении.addObject: сохраняет свой аргумент, означающий, что если вам больше не нужен этот термин, вам нужно отказаться от владения.То есть, передайте -autorelease результату вашего initToCall:::: (кстати, это очень плохое имя для метода)

...