What happens if your mark an autorelease object as autorelease - objective-c

My question may sound stupid an all, but I like to know what happens if I mark an autoreleased object as autorelease. Will it be released twice? Or nothing happens? For example:
Obj * obj = [[Obj create] autorelease];
Let's say [Obj create] returns an autoreleased object.
If I add another autorelease, what happens then?

Yes, sending autorelease twice will release the object twice. If your create method returns an autoreleased object and you send another autorelease message to it, your app will crash, because you'll be releasing a deallocated object.
Having said that, why don't you use the new Automatic Reference Counting (ARC)? You don't have to worry about (auto)releasing objects anymore.

You use the Class Method(+), you should not to care the memory. People use Class Method one reason is that it can return an autorelease object. If you release or autorelease the object which the Class Method returns, it will crash.

Related

The use of autorelease?

I am not clear about how to use autorelease;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
RetainTracker* tracker = [RetainTracker new];
[tracker retain];
[tracker retain];
[tracker autorelease];
[pool release];
Is there any memory leak in the above code?
I know the autorelease just puts tracker into NSAutoreleasePool, without modifying the reference count for tracker. When i call [pool release], the object receives one message release, then the reference count of tracker is 2. So the compiler can't call the dealloc function of object tracker, so there is a memory leak.
So i get this: we shoul call retain and release same times, is it right?
If you're new to Objective-c, you should be using Automatic Reference Counting. Almost everyone should. But for the sake of understanding:
An object has a reference count of how many objects have a reference to it. When it drops to zero, the object is not referenced by anything and is deallocated. Every method in Objective-C is responsible for releasing any object it retains. The problem is, if a factory method's job is to create an object, it's breaking the rules by not releasing an object it retained (in this example it was retained because it was created). If the method called release on the object right before returning it, it would be returning the address to an object that is already gone. So, there is autorelease, which temporarily delays the release until the calling method can retain the object the called method created.
In your example above, if you got rid of the 2 retains, and only called autorelease, then the object would get released and deallocated when the autorelease pool is released and (right before deallocation) is drained, meaning it calls release on all objects in its pool, tracker being one of them because calling autorelease on tracker added it to the pool.
new is equivalent to doing an "alloc" & "init", so retain count on tracker on that line is 1.
Then you increment the retain count 2 more times to give a total retain count of 3.
Autorelease sets the tracker to be released when the pool is released (and the retain count is decremented as well). But it's already retained 3 times, so it doesn't really get released.
And yeah, there is a memory leak with the retain count being greater than 0 and no reference to "tracker" outside of that method (that is, unless you're using "tracker" in an instance variable).
It's very good to know the basics of memory management; but if you want to save yourself a ton of headache, just do what everyone else here seems to be saying and simply enable ARC.
EDIT: And to finish your question, you should make sure every call to retain is balanced with a release. You also do a "new", which also increments the retain count so you need to "release" because of that as well.

Object with retain count 0 doesn't get released

Why is my object in the following leak trace doesn't get released?
The trace says its reference count is 0, so why doesn't it get released?
The object is a custom class that derives directly from NSObject. all I do with it is alloc it, init it, copy some strings/numbers from it, and send release, but still its considered a leak and doesn't get deallocated. I see it under allocations in instruments as 'living' so its really not deallocated. I create hundreds of these objects, so I cannot allow them to live.
How can I make this object get deallocated? why isn't it deallocated in the first place?
Well, it looks like you forgot to call [super dealloc] in your -dealloc method. We've all done that. :)
So the object is getting the dealloc call as you would expect, but isn't actually being deallocated.

Changing auto-released object to non-auto

Is there a way to change an autoreleased object to one that is non-autoreleased?
NSCoder's decodeObjectForKey returns an autoreleased object, which messes with a couple memory systems in my app. How can I change its returned value to a non-autoreleased object?
I know I can run retain on it, but if I release it, it'll still remain autoreleased. Whereas, I want to manage the memory myself.
Set up an autorelease pool before you retrieve the autoreleased object. It will be in that autorelease pool. Retain the object. Now release the autorelease pool. Your object is no longer in an autorelease pool. It's retained, and it's now your responsibility to release it.

Can I early-release an autorelease object?

i.e. would cause the object to be released immediately and not have to be released by the pool if I did this?
[[NSArray arrayWithCapacity:100] release];
Can't find a clear explanation in the docs about this.
It would likely crash when the object would normally be autoreleased. autorelease means "delayed release", so it will be released: just later. Since the object won't exist later as you are manually releasing it, you will likely crash due to the runtime sending the -release message to your now-deallocated object.
Edit: Note that if you -retain objects that come autoreleased, you do have to -release them: you are taking ownership.
I realise that this is stupid now, and that I shouldn't be releasing something I don't own.
If you don't want the object to go into the auto-release pool, you can do a manual alloc and initWithCapabity. If you do that, you'll have to manually release it at some point.

What is the difference between releasing and autoreleasing?

I still have some unclear understand about release and autorelease. What are the difference between both of them? I have this code. For facebook connection. I crash it sometimes when I go to Facebook login, I doubting maybe it is because I don't release the object nicely.? Thanks for any helps
if (_session.isConnected) {
[_session logout];
} else {
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease];
[dialog show];
}
The Memory Management Programming Guide for Cocoa will soon be your best friend. In brief, object instances in Cocoa are memory managed using reference counting (unless, of course you're using garbage collection on OS X). An object indicates that it wants to 'retain' an ownership interest in an other instance--keep it from being deallocated--by sending it a -retain message. An object indicates that it wants to release that interest by sending the other instance a -release message. If the number of objects that have 'retained' and ownership interest in an object drops to 0 (i.e. when the last of the owning instances sends a -release message), the instance with a 0 retain count is deallocated.
It's sometimes convenient to say "I want this instance to be released some time in the future". That's the purpose of -autorelease. Sending an -autorelease message adds the receiver to the current NSAutoreleasePool. When that pool is drained, it sends a -release message to all the instances in the pool. An NSAutoreleasePool is automatically created at the start of each iteration of each thread's run loop and drained at the end of that iteration. Thus, you can do something like this in a method:
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
The caller of this method will get back an instance that they can -retain if they wish to keep it. If they don't retain it, it will stick around at least until the enclosing autorelease pool is drained:
- (void)someOtherMethod {
...
id instance = [obj myMethod];
... // do more with instance, knowing that it won't be dealloc'd until after someOtherMethod returns
}
Releasing means you release that right away.
Autoreleasing means you want the variable to be released on the next autorelease pool.
You use autorelease when you want to keep retaining the variable but don't want to create a memory leak. You use release when you don't need the variable anymore.
Sample:
- (NSNumber *)return5 {
NSNumber * result = [[NSNumber alloc]initWitnInt: 5];
[result autorelease];
return result;
}
Why do we use autorelease there?
If we use [result release] instead, variable result will be destroyed AT that time. Which means that the returned value will be garbage.
If we do not release at all, variable result will be hold FOREVER incurring memory leak.
We can tell every caller to the function to release result but that would be a headache and prone to error.
So we use autorelease. We mark the variable to be released on the next autorelease pool. Basically we mark the variable to be released near the alloc. Hence the mantra alloc is paired with release in the same function holds all the time.
Actually, you'll do fine changing all release into autorelease. Your memory use won't be efficient, however, the effect is minimal. All variables, in all programming language is effectively autoreleased.
Anyway, use ARC.
background discussion:
objective-c is reference counted, so objects are deleted when the reference count reaches 0. release reduces the reference-count immediately, autorelease reduces it when the autorelease-pool is popped
when to use:
use autorelease when allocating the object if
you do not need it after the current function
it will be retiained by some other objet/function and will be released by a later by the retaining code
when the logic of the current function is tricky, so you would have to send release in a dozen different places before doing a return
use "manual" release
to revert a previous retain (in case you are implementing a library)
if you need precise control of freeing objects (e.g. they use lots of memory or the autorelease pool will not be popped for some time)
but really my freand:
read the Memory Management Programming Guide for Cocoa as suggested by Barry and run your code with instruments (zombies and leaks) often to catch any and almost all memory management errors.
Erik
According to the Memory Management Programming Guide for Cocoa:
The autorelease method, defined by
NSObject, marks the receiver for later
release. By autoreleasing an
object—that is, by sending it an
autorelease message—you declare that
you don't want to own the object
beyond the scope in which you sent
autorelease.
Also:
The autorelease method thus allows
every object to use other objects
without worrying about disposing of
them.