I have been using ojective c for almost a week, and I am mainly a c++ coder. After I read Apple's memory management guide, I try to bring my memory usage style in c++ into objective c... I tried to conclude these scenarios, I think I won't make memory mistake if I follow these instructions. Please kindly let me know if I am wrong :)
I will try not to use autorelease, personally speaking, by using autorelease, there might always be some redundent memory before certain auto release pool is drained. I will only use release, which make sure my application uses minimum memory at any time.
Another thing Apple says, which I describe with my own words, is: everytime I add an retain/alloc/copy, I should add a release somewhere.
Here are all the scenarios I conclude:
In the same function: alloc an object, use it, and release it
In the init function of a class, alloc an object, in the dealloc function of the class, release the object
When it's necessary to own a pointer, one should retain an input pointer in a method of a class(let's say method A), and then release the pointer in the dealloc function of the class.
I found that the timing of using retain in objective c is the same to the timing of using memcpy in c/c++, so I take retain as a "memory efficient copy"
If the input retained pointer is to set to a member pointer variable, then one should release the member pointer first. So in case[3], alloc in init of the class is paired with release in method A, and the retain in method A is paired with the release in dealloc
Return a pointer as return value. Honestly speaking I never do such things when I use c++. It's OK if to return a member pointer, coz someone will take care of it:
-(UIButton*) getTheButton() {
return theButton;
}
But it's really terrible to return a pointer to a locally allocated object:
-(UIButton*) getTheButton() {
UIButton* myButton = [[UIButton alloc] init];
return myButton; //TERRIBLE!
}
Someone might say I should use autorelease in that case, but I simply want to bypass that solution by using this: I will only return member pointers, or I will not return pointers, I will only operate on given input pointers.
-void operateOnTheButton(UIButton* button) {
[button release];
button = [[UIButton alloc] init];
}
So, please kindly let me know if there is any problem if I follow the memory usage instructions above.
Thanks :D
There is one important scenario where you must use autorelease
. If you alloc/retain/copy an object and then return it to some other code you own that object, but you can't release
it because other code needs to use it (or you wouldn't have returned it).
In this situation you must take responsibility for the object's release by sending it an autorelease
message, thereby ensuring it will eventually be released. This is exactly what foundation methods like NSString's stringWithString:
do. You don't have to release
a string object you get from this method because you didn't alloc/retain/copy it, but if the method hadn't autoreleased it for you it would survive the [pool drain]
and become a memory leak.
Make sure you understand how reference counting works. release
decrements an object's reference count. When the count reaches 0 the object is destroyed. alloc
and copy
create an object with a ref count of 1. retain
increments the receiving object's ref count by 1. For each alloc/retain/copy there must be one release
. 1 up, 1 down.
So when you return an object you created, passing control to the callee, you unbalance the 1 to 1 equation because you have no way to release
it. That's why there's autorelease
. It doesn't decrement the receiver's ref counter, so there's no danger it will be destroyed, but when the pool is drained each object in the pool gets one release
message for each autorelease
it has received, restoring the balance (unless an object was intentionally retained so it would survive the drain, in which case the callee would need to release
it later).
As for point 4, your second example is fine if you autorelease
, examples abound of this technique in the foundation classes. Every data class like NSString, NSArray, NSDictionary, etc. has methods that return locally allocated object pointers. They usually have the form thisWiththat:
, like stringWithstring:
or dictionaryWithContentsOfFile:
. The latter would allocate a dictionary object, populate it with the contents of the file, autorelease it, and return a pointer to you. Its called a factory function. Very common pattern in obj-c, java too.
You're third code example will cause a runtime error later. You are releasing an object you don't own. The owner will not expect you to release
it which will likely mean it will receive one too many release
messages, causing a runtime error. If you didn't alloc/retain/copy it, you don't own it so you shouldn't release it.