views:

94

answers:

2

I have some code that results in a EXC_BAD_ACCESS error:

recordIDAsString = [
 NSString stringWithFormat:@"%i", (int)abRecord.recordID
];
propertyIDAsString = [
 NSString stringWithFormat:@"%i", (int)abProperty.propertyID
];
identifierAsString = [
 NSString stringWithFormat:@"%i", (int)abProperty.identifier
];

recordIDAsString, propertyIDAsString, and identifierAsString are all defined in the interface. The code is contained in an editing view controller, and the three *AsString variables seem to work fine until the save button is pressed, when their values become invalid. However, I've discovered that the following code does work:

NSString *tempRecordIDAsString = [
 NSString stringWithFormat:@"%i", (int)abRecord.recordID
];
NSString *tempPropertyIDAsString = [
 NSString stringWithFormat:@"%i", (int)abProperty.propertyID
];
NSString *tempIdentifierAsString = [
 NSString stringWithFormat:@"%i", (int)abProperty.identifier
];

recordIDAsString = [tempRecordIDAsString copy];
propertyIDAsString = [tempPropertyIDAsString copy];
identifierAsString = [tempIdentifierAsString copy];

I thought I only had to manage memory when I call alloc or init, so my question is: what is happening in the first code example that causes the memory to become invalid?

+3  A: 

A string created via...

[NSString stringWithFormat:@"%i", (int)abRecord.recordID]

... is autoreleased. It will go away at the next autorelease pool -drain unless you -retain it.

You need to revisit the memory management guide:

http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

bbum
since I don't need the temp strings after getting their values, would it be best if I release them right away, or just wait for the autorelease pool -drain?
JoBu1324
Since stringWithFormat will autorelease, you shouldn't release. Refer to the memory management guide listed above. You should only release if you take ownership with copy, retain, alloc. You aren't doing that so you should let the autorelease pool do its thing. You could however use [[NSString alloc]initWithFormat:] and then you could release the string when you are finished. -- Although, you can simply do the recordIDAsString = [[NSString alloc]initWithFormat:] and then you would just release in you dealloc since it looks like recordIDAsString is an instance variable.
Brian
+2  A: 

NSString stringWithFormat is a convenience constructor - meaning that it will the returned object is autoreleased so that you don't have to do that. The issue that causes, is that if you want to keep that value, you must retain or copy it. So even though you are storing a reference to the value, you are not incrementing its retainCount. So when the current run loop is complete, the autorelease pool will send a release to all its objects decreasing the retainCount by 1. If you use a retain, you will increment the retainCount by one, so that when autorelease releases the object, it will still have a retainCount until another release is sent - which should be done by you at some point - maybe in your dealloc.

Brian