xCode - Почему эта утечка памяти? - PullRequest
0 голосов
/ 18 апреля 2011

У меня есть NSMutableArray, определенный следующим образом:

@property (nonatomic, retain)           NSMutableArray          *cList;

Я правильно разместил в моем dealloc выпуск для cList, а в селекторе я извлекаю некоторые данные из базы данных:

sqlite3 *database;

if(sqlite3_open([self.filePath UTF8String], &database) == SQLITE_OK) { 

    NSString *sqlStatement = [NSString stringWithFormat:@".....", self.someData];
    sqlite3_stmt *compiledStatement; 

    if (self.cList != nil) {
        [self.cList release];
        self.cList = nil;   
    }
    self.cList = [[NSMutableArray alloc] init]; 

    if(sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK) { 
        sqlite3_bind_text(compiledStatement, 1, [self.someString UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(compiledStatement, 2, [self.someOtherString UTF8String], -1, SQLITE_TRANSIENT);
        while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
            MyModel *newM = [[MyModel alloc] init]; 
            newM.d  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 0)];
            newM.c  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 1)];
            newM.i  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 2)];
            [self.cList addObject:newM];
            [newM release];
        }
    }
    sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);

Когда я работаю с Инструментами, он показывает мне некоторые утечки в этих строках:

        self.cList = [[NSMutableArray alloc] init]; 
...
        MyModel *newM = [[MyModel alloc] init]; 
        newM.d  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 0)];
        newM.c  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 1)];
        newM.i  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 2)];
        [self.cList addObject:newM];

с утечками: NSCFString и MyModel.Зачем?Я правильно выпустил объект cList.

Ответы [ 2 ]

3 голосов
/ 18 апреля 2011

Этот блок кода

if (self.cList != nil) {
    [self.cList release];
    self.cList = nil;   
}
self.cList = [[NSMutableArray alloc] init]; 

Может быть полностью заменен следующим:

self.cList = [NSMutableArray array];

Это устранит первую утечку.Не уверен, почему вы получаете предупреждение об утечке во втором блоке кода, так как вы правильно выпускаете newM.


Код протекает, потому что вы создаете объект и вступаете во владение им ([[NSMutableArray alloc] init]) и затем вы устанавливаете этот объект как свойство retain, снова приобретая право собственности на объект.Теоретически, вы могли бы обойти это, позвонив release дважды, но это глупо.[NSMutableArray array] возвращает автоматически освобожденный изменяемый массив.Установив для него значение retain, вы получаете право собственности на него один раз.

Кроме того, еще один маленький момент, нет необходимости проверять, является ли ваше свойство нулевым.Если вы хотите удалить свойство, просто сделайте self.cList = nil;.Среда выполнения будет обрабатывать освобождение переменной для вас;это одна из веских причин для использования @ properties.

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

Вызов 'alloc' возвращает ссылку-владельца (т.е. +1).Когда вы присваиваете его свойству «сохранить», вы увеличиваете счет сохранения, давая +2.Следовательно, когда вы отпускаете его позже, он просачивается со счетом сохранения +1.То же самое, когда вы добавляете newM в cList, он снова сохраняется, даже если вы уже им владеете.

Предлагаемые изменения:

    self.cList = [[[NSMutableArray alloc] init] autorelease];  // or [NSMutableArray array]
    ...
    MyModel *newM = [[[MyModel alloc] init] autorelease]; 
    newM.d  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 0)];
    newM.c  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 1)];
    newM.i  = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 2)];
    [self.cList addObject:newM];

Так что в обоих случаях вы используете autorelease, чтобы сказать, чтообъекты должны быть автоматически освобождены в будущем, если вы не сохраните их иным образом - что вы делаете благодаря свойству (retain) и добавлению в NSArray.

...