So I have several viewControllers, each creates images using "imageWithContentsOfFile" in order to conserve memory and then sets objects to nil and releases them in the dealloc method. There are no memory leaks. The problem is memory still builds up when switching views. So for example I'll be in view1 and it'll be using 8MB of memory and then I'll switch to view2 and back to view1 again and it'll be now using 10MB of memory. I've checked allocations in instruments and it's the images using it. Is there something I need to do to flush the memory out or something?
Thanks in advance!
Shouldn't you be calling [object release] before setting object = nil?
Sorry, I'm at home and I don't have a mac here so I can't test what happens when you do it the other way around.
Also, by saying there are no leaks, did you check using the Leaks tool? I don't think the tool detects all leaks, as I've tried putting a leak on purpose but Leaks wasn't able to see it.
Related
I have a question regarding autorelease pool and memory deallocation in an app I'm working on. If anyone needs to see the code I can post it.
First and foremost I'm using ARC in this app, now basically I'm allocating a good bit of memory on start up (images for an intro animation), and the memory they take up doesn't seem to properly deallocate until I receive a memory warning for one reason or another, or if I enter the background and re-enter the foreground of the app.
I've been monitoring the amount of memory being allocated in code as well as in instruments so it seems that this issue isn't some false positive. I know for a fact I'm properly disposing of the image memory as I clearly set the UIImageView.animationImages property to nil as well as set the UIImageView to nil and release it's parent view controller from memory once the animation is done. Basically, everything it has to do with is set to nil or removedFromSuperview to be sure that ARC knows it should be released.
Is there any way I can purge this autoreleased memory pool similar to the result of entering the background of the app or receiving a memory warning?
Figured it out, the UIImages I was allocating for my intro animation were being cached via imageNamed: method, therefore were retained even after they were autoreleased for some time.
To fix this I'm using imageWithContentsOfFile: method which does not cache the images.
I have been struggling with memory issues in my iphone app since weeks and haven’t been able to resolve the issue yet in spite of comprehensive research online.
Here is the case:
My application communicates with the Google Analytics API and is based on 3 basic views: Main view, setup view, and a tableview view that presents the data from google (with a custom cell). I have also constructed a custom class that fetches the data from google and then kills itself when done. All the data is stored in a singelton datacenter.
All views are initiated and then released as follows:
if (self.vVisitsTabelView == nil) {
visitsTabelView *initiatevisitsTabelView = [[visitsTabelView alloc] initWithNibName:#"visitsTabelView" bundle:nil];
self.vVisitsTabelView = initiatevisitsTabelView;
[initiatevisitsTabelView release];
}
[self.navigationController pushViewController:vVisitsTabelView animated:YES];
[vVisitsTabelView release];
vVisitsTabelView = nil;
The issue is that through every loading of the view memory increases, but when the view is popped it is not releasing memory although dealloc is being called and ALL instance variables are being released. This cycle happens over an over again (while re-loading the same view) and memory consumption becomes very high. After demanding use I even got to 200mb real memory and 320 virtual on instruments. Strangely a memory warning was received only once, however my app never crashed due to low memory and instruments indicates NO leaks.
After entering background the memory is slowly being released and used by other apps, however when I return to foreground memory is reclaimed back to the level before entering background (maybe form the virtual mem?). This process takes 9 seconds and in that time the app is frozen.
Any ideas how to attack this situation? I have searched everywhere and carefully followed all guidelines.
Any lead is highly appreciated...
Please excuse me if I didn’t follow guidelines, this is my first time on this wonderful place.
Thank you, can you elaborate slightly more how to do it?
Yes; you have a memory leak. Now, the Leaks instrument may or may not tell you what is leaking. It won't detect objects that are still somehow connected to the rest of the application; i.e. if a reference to the object is retained in an NSMutableDictionary somewhere that is still in use by the app, it won't be detected.
Since you know exactly which object is being leaked, it is a matter of figuring out what has retained it, but not released it. The Allocations instrument provides for exactly this capability. Specifically, you can configure the Allocations instrument to track retain counts.
This article may help http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/.
Also, there are a number of very similar question/answers on SO that address this. There is one in the last couple of weeks that I can't find that gave a great pictorial tutorial of how to do exactly what you want.
Have you checked the retain count on your views? [theView retainCount] will do this.
Either way you should strongly consider moving to ARC which is new for iOS5. You should be able to say goodbye to all your memory management woes.
My App tends to crash alot... :(
I know i've been making mistakes in deallocating the views and objects.. I just wanna knw apart from deallocating the memory in the last, how can i manage memory in between the code...
Also my most of the viewcontrollers uses -(void)ViewDidLoad to create the views..so shud i use -(void)ViewDidUnload too before deallocating the memory???
If yes, then plz guide me how to use it??
Also is there any other way to solve memory issues??? :(
Keep in mind that viewDidLoad can be called multiple times, this is especially true in low memory situations where view's can be automatically unloaded to save memory.
In this case you can either check if your object is nil before allocating it, or deallocate it in a memory warning (in didReceiveMemoryWarning, if self.view.superview == nil then things will be automatically released).
You should also get to know the profiling tools at some point, or at least the leaks profiler. In Xcode go to Run -> Run With Performance Tool -> Leaks. There are some issues with this tool you might hit, but once you come to grips you'll wonder how you lived without it (For instance if your host name has special characters in it you'll need to rename it).
If u have created any object in .h file and allocated it only once then u should deallocate that object
in this method:
-(void)dealloc
{
[myObject release];
[super dealloc];
}
but if u have created any object locally (in .m) file then release it at the place where it is not required any more.
What should I do when my app recieves a memory warning?
It all depends on your app, usually you don't have to do anything special except following Apple's recommended practices.
ViewControllers which are not visible at the moment will get didReceiveMemoryWarning message. By default (calling [super didReceiveMemoryWarning]) controller's view is unloaded (released, freed). As the view is unloading, view controller receives viewDidUnload where you should release all your IBOutlets (or otherwise retained UI elements). Only then the view can completely be deallocated and memory freed.
In the didReceiveMemoryWarning you should also free as much data as you can - if you store some part of data model in ViewController, release it, and reconstruct in viewDidLoad that would be called when your view is loaded again (when user navigates back to this controller). You can inform your model classes to free memory too.
It really depends on your app.
If your app downloads and caches lots of contents from Internet for example, you should purge as much as possible when receiving a warning.
If your app is an OpenGL game, you might have a texture/sound/data manager which references some unused data, which you then want to free. Cocos2D manages this kind of things.
If your app isn't memory intensive, you have a memory leak somewhere, and you should 1) read the Memory Management Programming Guide by Apple 2) use Instruments/Leaks.
In didReceiveMemoryWarning, you should release any cached or non-essential items to prevent running out of memory completely.
If you log or write to any other file, there might be an issue with "disk" space.
Also you should check for memory leaks.
I am trying to follow the Apple's recommendation to handle low-memory warnings (found in Session 416 of WWDC 2009 videos) by freeing up resources used by freeing up my dataController object (referenced in my app delegate) that contains a large number of strings for read from a plist:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[_dataController release];
_dataController = nil;
NSLog([NSString stringWithFormat:#"applicationDidReceiveMemoryWarning bottom... retain count:%i", [_dataController retainCount]]);
}
But when I run ObjectAlloc within Instruments and simulate a Low-Memory Condition, I don't see a decrease in the memory used by my app even though I see the NSLog statements written out and the retain count is zero for the object. I do pass references to the app delegate around to some of the view controllers. But the code above releases the reference to the _dataController object (containing the plist data) so I would expect the memory to be freed.
Any help would be appreciated.
Are you sure that app delegate is the only owner of _dataController? -release only decreases the ref count, it won't deallocate the object unless the ref count drops to zero.
If _dataController is owned by other objects too, send a message to them to release it.
I am double-checking that. Thanks for the input! I did reread the memory management docs from Apple and I did put an NSLog statement in the dealloc method of my DataController and it is being called. I also put wrote out the retain count before the release and setting to nil of _dataController. The retain count is 1.
So this drives me back to why I am not seeing a significant decrease in memory usage. I think I need to understand the ObjectAlloc display in Instruments better and where the largest allocations of memory are taking place in my app. After searching for help in this area, I am frustrated with trying to determine from Instruments where this occurs. I can see that there is 3.54 MB for "All Allocations" and 608 MB for Malloc 32.00 KB. If I drill down on Malloc, I only see the Responsible Caller as being framework calls like png_malloc and inflateEnd. I am looking for calls within my code that is responsible for the Malloc but I don't see that. All this to say that I wonder if I am releasing the object or objects that will really make a significant difference in the amount of memory used for the low-memory condition. I think I need an in-depth tutorial for Instruments. The Apple help docs are okay but an example with code would be more helpful.