Утечка вызвана удержанием или чем-то еще?(Objective-C) - PullRequest
1 голос
/ 05 августа 2011

Я использую Утечки, и я считаю, что сузил проблему, и я уверен, что моя неопытность как-то связана с этим.Если вы видите ошибку в моей логике (например, есть, очевидно, более простой способ сделать это), пожалуйста, дайте мне знать.

В этом случае мы работаем с 3 классами, классом Row, который описывает строкив базе данных, класс Database, который содержит функции getRow, insertRow и класс ViewController.

внутри Row.h:

@interface Row : NSObject {
int rowID;
NSString *FirstName;
NSString *LastName;

}

@property (nonatomic) int rowID;
@property (nonatomic, retain) NSString *FirstName; <--see comments below
@property (nonatomic, retain) NSString *LastName; <--see comments below

@end

Надеюсь, это довольно очевидно, создает объектчто я собираюсь выдвинуть данные, которые я извлекаю из базы данных.

внутри Database.m

-(Row *) getRow {
NSLog(@"Inside getRow");
Row *holder = [[[Row alloc] init] autorelease];

...All the SQL stuff... (Select * from table where id = 1), etc.


char *first = (char *)sqlite3_column_text(statement, 1);
char *last = (char *)sqlite3_column_text(statement, 2);

holder.rowID = sqlite3_column_int(statement, 0);
holder.FirstName = [NSString stringWithUTF8String:first];
holder.LastName = [NSString stringWithUTF8String:last];

return holder;
}

Кроме того, надеюсь, что это довольно очевидно.Получить конкретную строку из базы данных, поместить информацию в объект Row (см. Row.h).

внутри ViewController.m

-(void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    dataB = [[Database alloc] init];
    [dataB openDB];

    currentRow = [[dataB getRow] retain]; <--See comments below.

    firstNameLabel.text = currentRow.FirstName;

}

-(IBAction)btnGetLastName:(id)sender{
lastNameLabel.text = currentRow.LastName; <--See comments below.
[currentRow release];
currentRow = [dataB getRow];
}

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

Итак, у меня течь, и я сузил его до каждого нажатия кнопки btnGetLastName.Если я не сохраняю

currentRow = [[dataB getRow] retain]; 

, я вылетаю в

lastNameLabel.text = currentRow.LastName; 

(сообщение отправлено на освобожденный экземпляр).

Я бью себя по головеПару дней на этом, и я действительно хотел бы двигаться вперед отсюда, поэтому, если кто-то может предложить помощь, это будет очень цениться.Я также скажу, что это был опыт обучения, поэтому в некоторых случаях, если вам нужно спросить: «Зачем вы это сделали?»ответ может быть "потому что я тупой".Надеюсь, проблема здесь очевидна для кого-то.

Ответы [ 6 ]

2 голосов
/ 05 августа 2011

Хорошо, есть пара вещей, которые я вижу здесь, которые являются неправильными. Прежде всего, вы, вероятно, должны сделать currentRow сохраненным свойством, чтобы вам не приходилось его сохранять и освобождать самостоятельно. Также убедитесь, что ваш -dealloc метод вашего класса Row выглядит следующим образом:

- (void)dealloc {
    self.FirstName = nil;
    self.LastName = nil;
    [super dealloc];
}

Сделайте свой currentRow свойством так:

@property (nonatomic, retain) Row * currentRow;

Затем присвойте его как self.currentRow = aRow. Также обратите внимание, что вам также нужно установить self.currentRow = nil в методе dealloc. Скорее всего, ваше приложение дает сбой, потому что вы не сохраняете currentRow на линии currentRow = [dataB getRow];.

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

1 голос
/ 05 августа 2011

В методе Row dealloc вы выпускаете FirstName и LastName?

Это похоже на очевидное место в том, что вы описали для чего-то, чтобы быть чрезмерно сохраненным.Поскольку вы делаете holder.FirstName = [NSString stringWithUTF8String:first];, вы делаете удержание, используя синтезированный сеттер.Если вы не выпустите явно в dealloc (), то FirstName и LastName будут зависать.

0 голосов
/ 05 августа 2011

Может быть проблема с выпуском релиза для объекта автоматического выпуска.Поэтому я хотел бы сделать: Row * holder = [[Row alloc] init];

, и я верю, что вы освободили currentRow в вашем методе dealloc?

0 голосов
/ 05 августа 2011

При первом вызове getRow вы сохраняете результат (как и положено).Затем, когда кнопка нажата, вы отпускаете ее.Хорошо до сих пор.Тогда вы снова getRow, но не сохраняете это.

0 голосов
/ 05 августа 2011

Внутри getRow вы не освобождаете массивы символов, возвращаемые функциями sqlite3_.Это должно быть как минимум две утечки.

Сбой, если вы не сохраните currentRow, является противоположным: он освобождается в порядке, но до того, как вы закончите с ним, и его нужно сохранить, чтобы избежать этого, также в btnGetLastName.Обязательно выпустите его в dealloc.

0 голосов
/ 05 августа 2011

currentRow = [[dataB getRow] сохранить];

правильно. Если вы сделали self.currentRow = [dataB getRow] (где currentRow было сохраненным синтезированным свойством), это также будет правильным Когда вы обращаетесь к переменным-членам напрямую, вы выполняете присваивание, минуя синтезаторный установщик свойств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...