开发者

Releasing a pointer causes program to crash, even though the variable isn't used

I'm still slogging through learning memory allocation and Objective-C (my first run with开发者_如何学Python Leaks was unpretty, at best). Here is a current issue, I hope everyone can understand it, I've used some pseudo-code, but I don't believe I've left anything out.

I have a Row Class set for some database stuff, we'll use this:

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

I have a getRow function in my database class that looks something like this:

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

Now in my ViewController I have 2 functions of importance to this situation:

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

The second function is a button the gets the second word:

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

So, as you can see, using currentRow against causes the program to crash, and what I can't understand is that if I don't release rowPlaceholder the program works fine. At this point why does currentRow care about the data from another function, since it already has what it want (a value from getRow()).


What's going on here?

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

You create a row, then overwrite it with... I don't even know what getRow is in this context. There's no way this is compiling without warnings. Anyway, try using:

currentRow = [[self getRow] retain];

(Although, for the sake of convention, you should call the method just row.)

Without seeing the rest of your getRow method or Row class, I can't tell why the problem would be happening there.


autorelease means that the object in question will be automatically released. When this occurs is tied to when the autorelease pool is emptied, but for the default case it's when the UI "comes up for air" -- when your call chain returns back to the UI system code. If you're going to hold something "across" such a return to UI system code, you need to have it explicitly retained. In general, making it a retained property is the best way to do this (though of course you need to clear/release the property in your dealloc method).

[And why do you do this:]

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


When you allocate and init rowPlaceholder and then return it as autoreleased, that means its effectively ready to be cleaned up by memory management unless some other object retains it.

In the line:

currentRow=getRow

you are getting a copy of the pointer to the object returned by getRow but do not appear to be retaining it. (and getRow is autoreleasing it before returning it).

If currentRow is a property of your class then you need to refer to it as this.currentRow to ensure the accessor method is called (and it must be declared as a retain property). if its not declared as a property and is just an attribute of your class then you need to retain it manually.

The first time you reference currentRow.firstName is ok because there has been no loss of control by the current execution thread so the autorelease pool hasn't cleaned up this memory yet.

But once your thread loses control and give memory management a chance to clean it up, when you come back into the the btnLastName method the memory pointed to by currentRow (which is a pointer to the original memory allocated in the rowPlaceHolder = [[row alloc] init] call) has been released.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜