Освобождение указателя приводит к сбою программы, даже если переменная не используется - PullRequest
0 голосов
/ 03 августа 2011

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

У меня есть набор Row Class для некоторых вещей из базы данных, мы будем использовать это:

@interface Row : NSObject {
    int rowID;
NSString *firstName;
NSString *lastName;
}


В моем классе базы данных есть функция getRow, которая выглядит примерно так:

-(Row *) getRow 
{
  rowPlaceholder = [[Row alloc] init];    
       ...
  rowPlaceholder.rowID = column1;
  rowPlaceholder.firstName = column2;
  rowPlaceholder.lastName = column3;
       ...
    return [rowPlaceholder autorelease]; //<-----Problem is happening here
}


Теперь в моем ViewController у меня есть две важные для этой ситуации функции:

-(void) viewWillAppear:(BOOL)animated{
currentRow = [[Row alloc] init];
currentRow = getRow;
firstNamelabel.text = currentRow.firstName;
}


Вторая функция - кнопка, которая получает второе слово:

-(IBAction)btnLastName:(id)sender{
lastNamelabel.text = currentRow.lastName; //<---Crashes the program
}


Итак, как вы можете видеть, использование currentRow против вызывает сбой программы, и я не могу понять, что если я не освобождаю rowPlaceholder, программа работает нормально. На данный момент, почему currentRow заботится о данных из другой функции, поскольку она уже имеет то, что хочет (значение из getRow ()).

Ответы [ 3 ]

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

Что здесь происходит?

currentRow = [[Row alloc] init];
currentRow = getRow;

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

currentRow = [[self getRow] retain];

(Хотя для удобства следует вызывать метод просто row.)

Не видя остальную часть вашего getRow метода или Row класса, я не могу сказать, почему проблема возникла там.

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

autorelease означает, что рассматриваемый объект будет автоматически разблокирован.Когда это происходит, это связано с освобождением пула автоматического выпуска, но для случая по умолчанию это когда пользовательский интерфейс «выходит в эфир» - когда цепочка вызовов возвращается к системному коду пользовательского интерфейса.Если вы собираетесь провести что-то «через» такой возврат к системному коду пользовательского интерфейса, вам нужно это явно сохранить.В целом, сделать это сохраняемым свойством - лучший способ сделать это (хотя, конечно, вам нужно очистить / освободить свойство в вашем методе dealloc).*

currentRow = [[Row alloc] init];
currentRow = getRow;
0 голосов
/ 05 августа 2011

Когда вы выделяете и запускаете rowPlaceholder, а затем возвращаете его как автоматически освобожденный, это означает, что он фактически готов к очистке с помощью управления памятью, если только какой-то другой объект не сохранит его.

В строке:

currentRow=getRow

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

Если currentRow является свойством вашего класса, вам нужно ссылаться на него как this.currentRow, чтобы обеспечить вызов метода доступа (и он должен быть объявлен каксохранить собственность).если оно не объявлено как свойство и является просто атрибутом вашего класса, вам нужно сохранить его вручную.

При первом обращении к currentRow.firstName все в порядке, поскольку текущая потеря не была потерянапоток выполнения, поэтому пул автозапуска еще не очистил эту память.

Но как только ваш поток теряет контроль и дает управлению памятью возможность очистить его, когда вы возвращаетесь в метод btnLastName, память, на которую указывает currentRow (которая является указателем на исходную память, выделенную вrowPlaceHolder = [[row alloc] init] call) был освобожден.

...