What does the retain message mean? - objective-c

In Objective-C I see
[object retain];
What does sending a retain message to an object mean and why would I use it?

Basically it is used to take 'ownership' on an object, i.e. by calling retain, the caller takes the responsibility of handling memory management of that object.
Two very common usages of the top of my hat are:
1- you initiate an object with auto memory managed methods, but want it to hang around some time : someObject = [[someArray objectAtIndex:someIndex] retain], without retain the object will be autoreleased at some time you don't control.
2- you initiate an object by passing somePointer to it, you do your memory management and call release on somePointer, and now somePointer will hang around until the newly initiated object releases it, the object calls retain on somePointer and now owns it.
-(id) initWithSomePointer:(NSObject *)somePointer_{
if(self = [super init])
somePointer = [somePointer_ retain];
return self;
}
..
..
[somePointer release];

It ups the reference count on the object in question.
See this post for more details about reference counting in Objective C.

Read Apple's memory management guide for a complete and pretty simple explanation of everything to do with Cocoa memory management. I strongly recommend reading that rather than depending on a post on Stack Overflow.

Related

How to find where an Objective-C object is referenced from?

I'm using the Allocations instrument in Xcode to track an object that is being created but not released. I can see the object count increase as the code executes, and I can see where the objects are being created using the call stack, but I can't tell where the object references are being held. I think they're being held in a 3rd-party library, but the developer says "no, it must be your code". I'm setting the references in my code to nil, but the objects remain.
I don't think there exists a tool that will tell you where each reference is at any point in time. As you're using ARC, in my experience, there are two fairly common ways to get yourself caught in a reference cycle and leak memory:
Class A has a strong reference to an instance of class B, which has a strongly reference to the same instance of class A.
Blocks implicitly retain references to objects it captures. So one obvious gotcha is when your object retains a block which retains a reference to self.
Example:
self.retainedBlock = ^{
[self doSomething];
};
Fix:
__weak id weakSelf = self;
self.retainedBlock = ^{
id strongSelf = weakSelf;
[strongSelf doSomething];
};
It's a desperation ploy but what you could do is:
disable ARC for the affected object (or work around it; see below);
add a logging retain, autorelease and release;
trace a known over-retained object through your logs.
The simplest example:
- (void)release
{
NSLog(#"%# : %#", self, [NSThread callStackSymbols]);
[super release];
}
(though, in practice, it's probably a lot smarter to keep an array of [NSThread callStackSymbols] for the memory management calls in a dictionary indexed by e.g. [NSValue valueWithPointer:self], then to access that either from lldb or by writing it to disk; why bother effectively indexing the data by hand?)
Probably the easiest way to work around ARC is to write a single class with ARC disabled that can method swizzle your logging memory management methods onto the objects you want to track.

Confusion on dealloc calls

I have a basic question here.
I know that dealloc will be called when the object's reference count becomes zero,and dealloc releases all the resources hold by the object or frees memory, right?
The object reference count becomes zero if we send release message to that object right?.
Lets consider the following object with its property created as,
#property (retain) NSString* myString;//reference count 1
and dealloc
[myString release];//reference count 0
[super dealloc];
I am not releasing the myString object any where except in dealloc.
My question is who is making myString object reference count to zero so that dealloc will be called?
Please clarify my doubt.
Anything that maintains ownership of the object is responsible for releasing it. For example if the code you posted is the only thing that maintains ownership of the NSString stored in myString then when you call release the reference count will be decreased and the object will likely be deallocated (String literals are different). Now if you passed myString around or something else requested myString and retains it then that code is also responsible for releasing it which may be before or after you release it in the dealloc method.
I recommend referring to the documentation for reinforcing this concept.
Let's say your property myString is within your class MyClass. Each instance of your class is created and (presumably!) released. When that instance is [released], your dealloc method of MyClass is called. Your dealloc in turn calls release on your properties, which in turn invokes their dealloc, and so on until you reach the 'bottom' of this stack of objects using objects.
Your object will only be free'ed if the retain/release pairs match up. If you follow the cocoa memory management (see apple docs - advances memory management programming guide)
rules, you are the only 'owner' at that point - and running dealloc zap's the last reference away - free'ing the object.

Autoreleasing objects created in a thread and passed to another in objective-C

I have a method of an object which creates objects which are then passed to a method of another object in another thread, like this:
MyClass* myClass = [[MyClass alloc] init];
[anotherClass performSelectorOnMainThread:#selector(method) withObject:myClass waitUntilDone:NO];
in method, I immediately retain the object, supposing it will be somehow released by the creator. My question is: how do I make MyClass release that object correctly? Is this the correct way to go?
My solution was to release the object manually in method. I see anyway that the Leak analyzer still recognizes this as a leak and seems it is not what Apple recommends, as the owner has the responsability to release the object.
Can you explain me the correct way to handle this situation? Thanks!
I don't fully understand what you're trying to achieve, but in general:
You shouldn't worry about who and when releases/deallocates the object. Instead, just make sure to retain it when you (a single object or method of yours) start needing it and release it when you stop needing it (or autorelease it, in which case it will be released on the thread on which you called autorelease).
This is exactly the way the performSelectorOnMainThread:withObject:waitUntilDone: works. From the documentation:
This method retains the receiver and the arg parameter until after the selector is performed.
It retains them while it needs them for doing it's job.
In short, the mehod that creates the objects and sends them to another thread should be:
MyClass* myClass = [[MyClass alloc] init]; // retained, will need it for performSelector
[anotherClass performSelectorOnMainThread:#selector(method) withObject:myClass waitUntilDone:NO];
[myClass release]; // no longer needing it.
or
MyClass* myClass = [[[MyClass alloc] init] autorelease]; // will be released automatically, but guaranteed to be retained until this method returns
[anotherClass performSelectorOnMainThread:#selector(method) withObject:myClass waitUntilDone:NO];
The way you have it now is a memory leak.
The receiving method:
if it uses the object only internally, doesn't have to retain it, since performSelector does "until after it is performed" (the method returns).
if it needs it later, it should be assigned to a property which retains it.
Your question is very hard to understand because you talk about this object, that object, another object and use meaningless names like myClass, anotherClass and method. It remains unclear which object you intend to release and which one is reported as leaking.
Anyhow, multi-threading doesn't add any special complexity to reference counting. Certainly, your two object myClass and anotherClass aren't short-lived objects. So if you use autorelease, make sure that the reference counter doesn't go to 0 if all autoreleases have been executed.
It's perfectly okay to release either myClass or anotherClass or both in method.
You don't show a lot of code. But what you show is okay.

Objective-C Memory Management: When do I [release]?

I am still new to this Memory Management stuff (Garbage Collector took care of everything in Java), but as far as I understand if you allocate memory for an object then you have to release that memory back to the computer as soon as you are finished with your object.
myObject = [Object alloc];
and
[myObject release];
Right now I just have 3 parts in my Objective-C .m file: #Interface, #Implementation and main. I released my object at the end of the program next to these guys:
[pool drain];
return 0;
But what if this program were to be a lot more complicated, would it be okay to release myObject at the end of the program?
I guess a better question would be when do I release an object's allocated memory? How do I know where to place [myObject release];?
This is probably a little over-simplified, but in general, you are going to want to release it where you declared it.
If you declare an object INSIDE a particular method call, then by definition, you will be done with that object (or at least that handle to that object) at the end of that method call... release it then.
If you declare an object as an instance variable, then by definition you will be done with it when that instance is destroyed... release it in the dealloc method of that class.
Keep in mind that "release" does not equal "destroy." When passing objects around in your application, it may make sense to have more than one handle to that object stored in different places... in that case "release" means "I'm done with this object, but someone else may still be using it." Deallocation only occurs when the number of "handles" (retain count) reaches zero.
Apple has some fantastic documentation on memory management, I would check it out at developer.apple.com.
You essentially have three kinds of objects, each with a different pattern.
Transients Objects
In general, you should autorelease transient objects. These are objects that are allocated locally and do not need to exist beyond the method in which they are called. Or they are passed around from method to method.
Chain of Ownership
When one object exists as an instance field inside another, you should release the "owned" (or "child") object when the "owner" (or "parent") object goes out of existence. This is done in the dealloc method of the parent object:
- (void) dealloc {
[child release]; // child was declared as an instance variable
[super dealloc];
}
Lifetime of the Program
When an object is intended to exist for the lifetime of the program, it usually isn't necessary to call release at all, unless some kind of resource cleanup needs to occur. You can put this in applicationWillTerminate:, which you can look up in Apple's documentation.
(You should probably avoid having such objects, but that is a discussion for another question.)
You have to think in terms of ownership. When you take ownership of an object by calling alloc, new or retain, you're also responsible for releasing it, either by calling autorelease when you return an owned object to the caller, or by calling release.
A general rule is:
Local variable: release it within the same method. When you want to return it to the caller, use autorelease
Class member: release it in the dealloc method

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.