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

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.

Related

Why does this GCD example code seem to improperly release an object?

In wikipedia example author has released the object stats, when it has not been allocated, copied, or retained. Is this an error or something I don't understood?
- (IBAction)analyzeDocument:(NSButton *)sender
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSDictionary *stats = [myDoc analyze];
dispatch_async(dispatch_get_main_queue(), ^{
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
[stats release];
});
});
}
It is either an error or it is properly documented that analyze returns ownership of the object to the caller. If it is not an error that stats is released then that codes example is using a convention that goes against Apple's memory management rules for ownership.
Memory-management rules, sometimes referred to as the ownership
policy, help you to explicitly manage memory in Objective-C code.
You own any object you create by allocating memory for it or copying
it.
Related methods: alloc, allocWithZone:, copy, copyWithZone:,
mutableCopy, mutableCopyWithZone:
Another prefix that should return ownership is the class method +new. E.g. [MyDocClass newAnalysis];
This is just an example cooked up by John Siracusa to demonstrate how GCD can easily put a long-running task into the background, but, yes, it has one of two problems, one an ingored convention, the other an actual error.
It's possible that the fictional analyze method returns an owning reference. This is a violation of Cocoa convention that methods not named new, alloc, release, or copy... generally don't return such references, but if the documentation made clear that it did, and there was really no way around it, it could be all right. In this case, sending release to stats would be necessary to avoid a memory leak. (If this were real code, renaming the method would be a good idea, perhaps using create which is used in CoreFoundation to signify return of an owning reference.)
If, however, analyze follows convention and returns a non-owned reference, then you're right, sending release to stats is incorrect and will eventually cause a crash.
Most likely analyze is returning a dictionary with a retain count of 1 which is why the release is needed.

Why does ARC retain method arguments?

When compiling with ARC, method arguments often appear to be retained at the beginning of the method and released at the end. This retain/release pair seems superfluous, and contradicts the idea that ARC "produces the code you would have written anyway". Nobody in those dark, pre-ARC days performed an extra retain/release on all method arguments just to be on the safe side, did they?
Consider:
#interface Test : NSObject
#end
#implementation Test
- (void)testARC:(NSString *)s
{
[s length]; // no extra retain/release here.
}
- (void)testARC2:(NSString *)s
{
// ARC inserts [s retain]
[s length];
[s length];
// ARC inserts [s release]
}
- (void)testARC3:(__unsafe_unretained NSString *)s
{
// no retain -- we used __unsafe_unretained
[s length];
[s length];
// no release -- we used __unsafe_unretained
}
#end
When compiled with Xcode 4.3.2 in release mode, the assembly (such that I'm able to understand it) contained calls to objc_retain and objc_release at the start and end of the second method. What's going on?
This is not a huge problem, but this extra retain/release traffic does show up when using Instruments to profile performance-sensitive code. It seems you can decorate method arguments with __unsafe_unretained to avoid this extra retain/release, as I've done in the third example, but doing so feels quite disgusting.
See this reply from the Objc-language mailing list:
When the compiler doesn't know anything about the
memory management behavior of a function or method (and this happens a
lot), then the compiler must assume:
1) That the function or method might completely rearrange or replace
the entire object graph of the application (it probably won't, but it
could). 2) That the caller might be manual reference counted code, and
therefore the lifetime of passed in parameters is not realistically
knowable.
Given #1 and #2; and given that ARC must never allow an object to be
prematurely deallocated, then these two assumptions force the compiler
to retain passed in objects more often than not.
I think that the main problem is that your method’s body might lead to the arguments being released, so that ARC has to act defensively and retain them:
- (void) processItems
{
[self setItems:[NSArray arrayWithObject:[NSNumber numberWithInt:0]]];
[self doSomethingSillyWith:[items lastObject]];
}
- (void) doSomethingSillyWith: (id) foo
{
[self setItems:nil];
NSLog(#"%#", foo); // if ARC did not retain foo, you could be in trouble
}
That might also be the reason that you don’t see the extra retain when there’s just a single call in your method.
Passing as a parameter does not, in general, increase the retain count. However, if you're passing it to something like NSThread, it is specifically documented that it will retain the parameter for the new thread.
So without an example of how you're intending to start this new thread, I can't give a definitive answer. In general, though, you should be fine.
Even the answer of soul is correct, it is a bit deeper than it should be:
It is retained, because the passed reference is assigned to a strong variable, the parameter variable. This and only this is the reason for the retain/release pair. (Set the parameter var to __weak and what happens?)
One could optimize it away? It would be like optimizing every retain/release pairs on local variables away, because parameters are local variables. This can be done, if the compiler understands the hole code inside the method including all messages sent and functions calls. This can be applied that rarely that clang even does not try to do it. (Imagine that the arg points to a person (only) belonging to a group and the group is dealloc'd: the person would be dealloc'd, too.)
And yes, not to retain args in MRC was a kind of dangerous, but typically developers know their code that good, that they optimized the retain/release away without thinking about it.
It will not increment behind the scenes. Under ARC if the object is Strong it will simply remain alive until there are no more strong pointers to it. But this really has nothing to do with the object being passed as a parameter or not.

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 does the retain message mean?

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.