Утечки памяти в приложении iphone - PullRequest
0 голосов
/ 29 июля 2011

Привет, ребята! я новичок в разработке iphone. У меня проблемы с утечкой памяти. У меня есть такой код.

do {

    int s = sqlite3_step(statement);
    switch (s) {
        case SQLITE_ROW:{

            Article *a = [[[Article alloc] init] autorelease];
            for (int i = 0; i < columnCount; i++) {
                const char *columnName = sqlite3_column_name(statement, i);
                if(strncmp(columnName, "title", strlen("title")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr != NULL)
                        a.title = [[[NSString alloc] initWithCString: colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "author", strlen("author")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr != NULL)
                        a.author = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "description", strlen("description")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr != NULL)
                        a.description = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "link", strlen("link")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if (colStr) 
                        a.link = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "imageUrl", strlen("imageUrl")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if (colStr)
                        a.imageUrl = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
                if(strncmp(columnName, "pubDate", strlen("pubDate")) == 0){
                    const char* colStr = (char*)sqlite3_column_text(statement, i);
                    if(colStr)
                        a.pubDate = [[[NSString alloc] initWithCString:colStr encoding:NSUTF8StringEncoding] autorelease];
                    continue;
                }
            }
            [array insertObject:a atIndex:0];
        }
        break;
        case SQLITE_DONE:
            sqlite3_finalize(statement);
            dataForReadingAvailable = NO;
            break;
        default:{
            NSLog(@"getArticlesForFeed:sqlite3_step failed.Error:%s",sqlErrMsg);
            return nil;
        }
        break;
    }   
}while(dataForReadingAvailable);

Инструменты из XCode показывают, что у меня есть утечка памяти, когда я выделен объект и когда я инициализировал его свойства. Но почему это происходит? Все объекты являются автоматически выпущенными в продажу, поэтому я думаю, что не будет такой ситуации. Спасибо.

1 Ответ

0 голосов
/ 29 июля 2011

Я думаю, возможно, вы перезаписали выделенную память новым указателем где-то.

Я бы заменил

Article *a = [[[Article alloc] init] autorelease];

с

Article *a = [[Article alloc] init];
//some code
[a release]; //when you don't need it anymore

Это не очень хорошая практика, чтобы использовать авто-релиз много. Это может даже замедлить ваше приложение, кстати, в случае многих объектов. И струны, как

 a.title = [[[NSString alloc] initWithCString: colStr encoding:NSUTF8StringEncoding] autorelease];

Я бы заменил на

 a.title = [NSString stringWithCString:colStr encoding:NSUTF8StringEncoding];

В этом случае вы также полагаетесь на пул автоматического выпуска, но это намного проще.

EDIT: Действительно, ваше выделение «Статьи» находится в цикле do-while. В строке [массив insertObject: a atIndex: 0]; ваш массив сохраняет объект, и он вам больше не нужен, но вы полагаетесь на авто-выпуск. Анализатор (или какой инструмент вы используете) видит, что вы поместили выделение в тело цикла, не освобождая его после каждой итерации. Таким образом, на второй итерации цикла вы перезаписываете свой объект «a», таким образом теряя старый указатель и теряя память (пул не найдет этот указатель, поскольку «a» перезаписывается). Даже если вы пройдете цикл только один раз, анализатору все равно, и вы получите предупреждение.

...