I'm almost done with and app and I'm using instruments to analyse it. I'm having a problem with ARC deallocating something, but I don't know what. I run instruments using the allocations tool ,what I'm doing is starting the app at the main view, then I mark a heap, I interact with the app a little and return to the original main view and mark another heap.
I do this several times and as I understand it, there should not be any significant heap growth because I am returning to the exact same place, everything I did in between should have been deallocated, providing no heap growth. However I have significant growth so I dive into the heaps and I find that almost everything on it has a retain count of 1, which leads me to believe that one object or view, etc is not being deallocated because of a mistake I've made and that object is what's holding references to everything else.
What I'm trying to find out is which object is not being deallocated. Instruments is very vague and only offers obscure pointers that do not allow me to trace back the problem.
Please let me know if there is a way for me to trace what is holding a reference that may be keeping the retain count at 1.
Thanks.
My 1st thought are 2 things:
1) You may have a retain cycle: As an example, one object has to a delegate a strong reference. And the delegate has also a strong reference (instead of a weak reference) to the 1st object back. Since both of them "hold" the other one, none of them can be released.
2) You may have a multi-threaded app, one of the threads does not have an autorelease pool assigned (i.e. does not have an #autoreleasepool block), and is creating autorelease objects. This may happen even in a simple getter method that returns an autorelease object. If so, the autorelease object is "put" into an non-existing autorelease pool (which does not give you an error message, since you can send any message to nil), and it is never released.
Maybe one of these cases applies to your problem.
Related
As a test to ensure that scenes are being dealloc'd i've been adding the:
-(void)dealloc{
NSLog(#"scenename Dealloc);
}
I've noticed that sometimes this method isn't called, i had previous issues with retain cycles which i believe i fixed, the main issue is that surely if it gets called sometimes it should be called every time?
I've also heard that using the nslog in this method in the scene causes its to be overwritten and therefore not called correctly, resulting in the scene not being dealloc'd, is this true? Could this be the problem causing the game to crash at present? I do see memory fluctuations (up and down) even with these log messages in place.
If you want to see exactly what objects exist within your game at different points you can use the Allocations instrument. You can find it under XCode > Open Developer Tool > Instruments
arrange the list by name, and look for the name of your project. You should see how many of your different game objects exist in memory there.
As has been previously suggested by the people above i had a memory leak and this was resolved via debugging and instruments.
In my Cocoa project I had a bunch of places where I used malloc/free. However several months ago I decided to refactor to leverage ARC and in order to do that I tried to make a replacement for malloc which will return a pointer to something that will be automatically cleaned up.
I used this function (error checking and other logging omitted)
+ (void *) MallocWithAutoCleanup: (size_t) size
{
NSMutableData * mutableData = [[NSMutableData alloc] initWithLength:size];
void * data = [mutableData mutableBytes];
return data;
}
This worked fine for awhile, but recently a random memory overwrite issue came up. I tracked down the cause to this function, what appears to be happening is the NSMutableData instance is being deallocated even though I am keeping a pointer to its mutableBytes.
I guess this is happening because the only direct reference to the object is local and is going away, and the mutableBytes points inside the object so the ARC isn't smart enough to deal with that sort of reference counting.
Is there any way I can refactor this code to retain the mutableData object as long as the mutableBytes pointer is being used (i.e. someone has a reference to it)? I know one option is to just return the NSMutableData itself, but that requires some heavy refactoring and seems very messy.
In the 10.7 SDK, -[NSMutableData mutableBytes] is decorated with the NS_RETURNS_INNER_POINTER attribute. This signals to the compiler that the method returns a pointer whose validity depends on the receiver still existing. What exactly ARC does with this is open to change, but currently it retains and autoreleases the receiver (subject to redundant operations being optimized away).
So, the pointer is valid for the duration of the current autorelease pool's lifetime. This is akin to -[NSString UTF8String] (which is decorated in the same way).
ARC is not capable of keeping the mutable data object alive so long as there's any reference to the byte pointer. ARC is not a garbage collector. It doesn't watch all uses of all pointers. It operates locally. It examines one given function, method, or block and emits retains and releases for the behavior of the code as indicated by naming conventions. (Remember that ARC is interoperable with code which hasn't been compiled with ARC support.)
Since a void* isn't an object pointer and can't be retained or released, ARC can't do anything with it. So, in the code calling your -MallocWithAutoCleanup: method, ARC doesn't see anything it can manage. It doesn't emit any special memory management code. (What could it emit at that point?) While compiling the caller, the compiler likely doesn't know anything about the method implementation or the mutable data object inside it.
Think about it another way: if you were still writing manually reference counting code, what would you do in the caller of your method to keep the pointer valid? For the most part (ignoring __weak references), all ARC does is automatically do what you would do manually. Once you consider that you would have no options in that case, you realize that neither does ARC.
I think you answered your own question. If you want to use NSData to manage generic memory allocations, you need to keep a reference to the NSData objects around until you're done with the memory it owns, at which point you nil out your reference(s) to the NSData object in question. This doesn't seem to provide any advantage compared to just manually freeing the malloced memory. Personally, I'd continue to use malloc()/free() explicitly instead of trying to contort my code in such a way that ARC kind of sort of manages malloced memory.
Either that, or I'd write my code such that it doesn't have to use malloc/free in the first place. I'd say the typical "pure" Cocoa project doesn't have many, if any, explicit malloc() calls, and I'd be a little suspicious of code that did unless there was some good reason for it. Why are you using malloc() in the first place?
First, I should say I'm using ARC, so retain is not an option. The object's class is of type NSViewController and has two NSTimers as well as several textfields and buttons. The odd thing is that when the two timers are invalidated, it looks like the object is being released. This is a problem because sometimes I just want to pause or restart them, which means I have to invalidate them, but once I do, the reference is lost, and any message to the object will throw a EXC BAD ACCESS.
I'm not very familiar with memory management or ARC but why is the reference lost depending only on the timers? I mean, just because they're invalidated does not mean I don't need the object anymore.
I've tried declaring the timers as instance variables and properties but nothing changed.
What I really need is for the reference not to be retained, even when both timers are invalidated. What am I doing wrong?
NSTimer retains its target, so if it is the only reference to the object it will be deallocated when the timer is invalidated. You'll have to take ownership of your object, preferably by making it a declared strong property.
Edit: Changed "delegate" to "target";
Yes, you'll have to declare a property and (possibly) an instance variable for it.
The release notes give a good example, there are a couple other good intros around. Make sure that you invalidate the timer if your owner class is ever deallocated, otherwise your view controller will hang around.
I'm using a UITableView to show some data from an array. This array can be changed at any time by other threads. (I believe that whether the array is mutable, or just replaced entirely, doesn't make a difference.) Access to the array itself is threadsafe.
What's the proper way to ensure thread safety with regard to the tableview? I'm worried, for example, that I might change the array to be shorter just before cellForRowAtIndexPath is called, leading to an NSRangeException.
Should I...
Enforce that the array is only changed on the main thread? (Seems ugly.)
Maintain a shadow array and update this on the main thread through KVO observing?
??? There must be a better solution...
From your description, you really have TWO different data sets:
The actual data, as it exists in your model
The data that's displayed to the user
Thus, you already have, in effect, a 'shadow' array (virtual shadow, which may be stretching the metaphor too far). I'd say your best bet is to formalize this arrangement, and keep a 'display' array that only gets modified in the main thread. In it, you can have objects from your 'real' array; since they're only pointers, you won't be giving up too much memory.
Threading is evil.
Without knowing more about your app, I think one of the better solutions would be to keep the array on the main thread and dispatch back to it whenever another thread needs to make a change. Like this:
dispatch_async(dispatch_get_main_queue(), ^{
[array addObject:object];
[tableView reloadData];
});
Of course, you can get much more complex with the dispatch API, but it does handle locking and everything for you. Definitely more elegant than using an NSLock. It does only work on iOS 4 or later though.
I have the same situation. I have an array of C++ objects that provide the info in the tableview.
As Ben referred to, I also have a temporary "shadow" array into which new information is downloaded over the Internet. When the query is complete, I reconcile that array with the one backing the tableview, which is quite fast. The question is how to protect the array during that reconciliation.
I'm doing the reconciliation on the main thread, but I'm not sure that's sufficient to protect from conflicts, especially if the user taps on an entry while there's a query pending; the underlying object he's viewing details for might be blown away.
There's a similar question to yours (and mine) here:
Update UITableView using threads
but the answers berate the poster for taking too long with his background operation, instead of answering his question.
I'm going to use an NSLock, and acquire it before altering the array and in all of the UITableView delegate methods, unless somebody has a better idea.
When I've registered an object foo to receive KVO notifications from another object bar (using addObserver:...), if I then deallocate foo do I need to send a removeObserver:forKeyPath: message to bar in -dealloc?
You need to use -removeObserver:forKeyPath: to remove the observer before -[NSObject dealloc] runs, so yes, doing it in the -dealloc method of your class would work.
Better than that though would be to have a deterministic point where whatever owns the object that's doing the observing could tell it it's done and will (eventually) be deallocated. That way, you can stop observing immediately when the thing doing the observing is no longer needed, regardless of when it's actually deallocated.
This is important to keep in mind because the lifetime of objects in Cocoa isn't as deterministic as some people seem to think it is. The various Mac OS X frameworks themselves will send your objects -retain and -autorelease, extending their lifetime beyond what you might otherwise think it would be.
Furthermore, when you make the transition to Objective-C garbage collection, you'll find that -finalize will run at very different times — and in very different contexts — than -dealloc did. For one thing, finalization takes place on a different thread, so you really can't safely send -removeObserver:forKeyPath: to another object in a -finalize method.
Stick to memory (and other scarce resource) management in -dealloc and -finalize, and use a separate -invalidate method to have an owner tell an object you're done with it at a deterministic point; do things like removing KVO observations there. The intent of your code will be clearer and you will have fewer subtle bugs to take care of.
A bit of extra info that I've gained by painful experience: although NSNotificationCenter uses zeroing weak references when running under garbage collection, KVO does not. Thus, you can get away with not removing an NSNotificationCenter observer when using GC (when using retain/release, you still need to remove your observer), but you must still remove your KVO observers, as Chris describes.
Definitely agree with Chris on the "Stick to memory (and other scarce resource) management in -dealloc and -finalize..." comment. A lot of times I'll see people try to invalidate NSTimer objects in their dealloc functions. The problem is, NSTimer retains it's targets. So, if the target of that NSTimer is self, dealloc will never get called resulting in some potentially nasty memory leaks.
Invalidate in -invalidate and do other memory cleanup in your dealloc and finalize.