I have an app that has a tabBar Controller and a navBar Controller. It has ~8 views (a variety of web, table, standard, mail, address etc.), some created using IB some created using XCode to make the table views. I've ran the memory leak tester and it doesn't have memory leaks. It can crash at anytime on any of the views, If I flip back and forth between views and use some of the functions it closes the app.
I assume that either I am running 1) out of memory or 2) not releasing views correctly, which causes the app to close. The app is simple so I don't know how I could be out of memory and I've reviewed the code to the best of my ability for releasing the objects correctly.
So Here is my list of questions:
1) What and How to use some of the other debugging tools (or tell me what tools/files I should be looking for using)? I would like to narrow down the problem to its source.
2) What is the best practice for releasing these views? How?
3) How much memory do normal apps use? Is there a number that I should stay around? How do I verify that in the simulator? the Allocation tool?
Feel free to point me to apple docs or other stackoverflow questions that can help me.
UPDATE: It appears to only be crashing one view is used, which has a table view with custom cells... The cell are populated from a plist file... this view worked fine a few days ago, I notice that some cells do not have data from the plist file... it could be a plist file problem with not storing proper data. I'll continue to work on it.
UPDATE #2: I went back to older rev of my files, to when this particular tableView worked just fine (pre 3.0) and guess what it works just fine, I change the simulator to 3.0 with this rev of the app and bam crash on this tableView shows up. Thanks for the help so far, I'll try somethings mentioned below and let you know what I find. If you have some tips on why a tableView w/custom cells from 2.2.1 to 3.0 would start crashing, I'll take them. If I can't get anywhere I'll post the code soon. BTW, I mis-spoke above, I thought it wasn't crashing in the simulator... I was wrong it is.
Solution: thanks for the troubleshooting tips the fix was quite simple, but it's odd it didn't crash in 2.2.1... it should have crashed a long time ago for the problem, I was releasing an object one to many times in my custom cell... duh.
On the first and second generation phone's you really don't want to be going over about 20 megs of real memory usage - once you get over that you are at risk of being killed by springboard.
One of the big culprits I've seen is autoreleased memory, since the autorelease pool can hold onto memory a lot longer than you would really like - if you are using a lot of autoreleased objects that can be a potential problem. You can improve this by doing more explicit retain/release where possible and by creating local autorelease pools manually and releasing them after doing a more intensive operation with a lot of autoreleased objects.
The most effective way to keep track of real memory usage I've found so far is running a debug build on a test phone and running with Activity Monitor. That will give you a clear idea of how much memory is getting taken and held onto by your app. As well as how much is being used when it crashes on you.
You can run with Activity Monitor in Xcode on the Run menu -> Start With Performance Tool -> Activity Monitor.
One other very useful tool is the CLang Static Analyzer that you can run against your code base and can give some very helpful memory management information. As mentioned here.
One thing I would try is putting some debug messages into your didReceiveMemoryWarning method(s). That way, if you are running out of memory, you'll at least have some warning.
Related
In my app user can take as may picture from camera, so after three time taking the picture it crashed. I can't resize the image (its requirement). So is there any other way to avoid memory leak.
Thanks
There is a know issue with the uiimagepickercontroller with memory leaks.
Apple recommend that you only allocate and instantiate only one instance and store it somewhere for the life of the application (whilst running that is).
Don't create a new one, use it and deallocate it each time you want to
use the control. If you do, your memory usage will keep increasing
until it crashes your app.
Personally I store it as a property in the appDelegate, but there may be a better way of doing it.
Edited: Thanks to CharlieMezak. Yes, such a leak might cause a crash. You'd better do some checking based on CharlieMezak's suggestions.
What may also cause crash is your code trying to access a piece of memory that was deallocated already.
I suggest you first check your code to see if there is any autorelease object that was not taken care of.
Second, turn on NSZombieEnabled, and test your app. If it's indeed trying to access something that was already deallocated (Zombie), the console will show you.
Third, and most importantly, post your crash report and part of the code that might be responsible for such a crash. Your description is somewhat vague, we need to see the report.
It sounds like your app is able to handle the photos correctly (from the user's perspective) two times, but on the third time it crashes. Sounds to me like a memory leak.
If it were a logical error in the code, or an attempt to access a deallocated object, the crash would probably occur the first time you take a photo.
It sounds like you're leaving the images in memory, so by the time you take your third photo, you're out of memory because the first two are still sitting there. Make sure you're releasing what you retain, and if you continue to have trouble, post your code!
I am working on an App that is already been made but Memory Management was not considered in the development stages.
So what can I do to keep the App memory usage low as soon as I get a memory warning?
Is there any general tool or some piece of code that I can use to release any unused memory?
Two things.
First, if you're using any sort of view hierarchy (tab bar, UINavigationController, or something you've rolled on your own), the message is going to propagate upward. That means one handler for memory messages in your root-level UIViewController subclass can handle memory events for the whole app, which is very handy.
Second, you want to go after the low-hanging fruit. In the app I'm currently working on I have a couple different arrays of dictionaries that contain my app data, and each of those dicts contains both a thumbnail and a larger image. Obviously those make up the bulk of the bits I'm keeping in memory. So the first thing my root view controller does when it gets a memory warning is go through those data sets and set those images to nil. Because they're retained properties, they get released when the setter is called and the images are freed from memory. Then I have functions in my view controllers to notice the nil-ness of those image fields and reload them from the server.
By the way (okay... two things and a "by-the-way"), memory warnings aren't a problem. Some people seem to feel bad about getting them, want to redesign everything about their app so they never get one. That's really not necessary; even the best-designed app will get warned about memory occasionally, just because of the unpredictability of the background apps on the device. The important thing is to handle them well.
Xcode can be combined with the Instruments tool to show you the places where your application is leaking memory, i.e. where reserved memory is not released properly. CIMGF has a solid tutorial on this: http://www.cimgf.com/2008/04/02/cocoa-tutorial-fixing-memory-leaks-with-instruments/
You should have a look at the method
- (void)didReceiveMemoryWarning
of your UIViewControllers. This method is called when you receive a memory warning. Here you can release objects currently not used. But it's your part to determine what is used and what not.
The "Build and Analyze" feature of XCode is a tool you could use to see if the code contains any obvious memory leaks.
You should have a look at the small section "Memory Management" in the UIViewController class reference:
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html
Also an important document is the "Memory Management Programming Guide":
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
I have a UIViewController and I'm noticing that I've done something to where the didReceiveMemoryWarning method is getting called every time I run it on an actual device.
I've run the project with Run > Run With Performance Tool > Object Allocations (and Leaks also). There are no leaks but I have no idea how to read or understand the "Object Allocations" data that is displayed.
So ...
How do I read this information and what is/are the best ways to figure out (and resolve) why this is happening?
Thanks
EDIT:
I should mention that I also have a number of 3rd party libraries/code that I've included in my project (e.g. Three20, MGTwitterEngine, FTUtils, extThree20JSON and Twitter+OAuth). Could this be causing this??? Or at least contributing to the problem?
EDIT #2:
Don't know if this helps but I notice that this is happening either everytime that I present a UIImagePickerController modally -OR- after a take a picture using it.
* UPDATE *
Ran it again with the Object Alloc tool for several minutes and I don't see anymore than 4.75MB being allocated at any given moment. The app was running on a device and typically with 2.5 MB allocated on average.
Does this seem problematic to anyone??? Seems like its in an acceptable range insofar as I understand thing.
This may happen some time when your device have less memory free to use. Check your device free memory.
The problem had to do with UIImagePickerController ... and all is answered in this post: Received memory warning. Level=1 when showing a UIImagePickerController
I've developed my application using my 3G device to test with. Upon giving this to a friend to test, he's noticed that it crashes..I've had a look at the crash log, but it's not much use except for the "EXC_BAD_ACCESS" statement after a few memory warnings.
On my device, I can use the imagePicker lots, and each time a photo is taken I get a memory warning, but this doesn't cause any problems.
On my friend's device (also a 3G), after a couple of images chosen from the camera, the app crashes.
So, my question is.. I think something is being deallocated because of the memory warning - but only on my friend's device, and then after deallocation, it's trying to be used again. How can I find out what object is being called? I can't use NSZombies because this is a remote (beta) device.
Help please!
Also if anyone has any ideas why my device can pick image after image without any problem and his can't...that would be most helpful
Thanks!
EDIT: New discovery.. I'm getting this error message too: KERN_PROTECTION_FAILURE which I understand to be something to do with data access. The crash seems to happen right after I save the image got from the UIImagePicker. Any ideas?
You may be over-releasing something. If you're running Snow Leopard, run the Static Analyzer (Cmd-Shift-A) and look for memory errors.
The fact that it crashes after a memory error suggests that a UIViewController has released its view. Do you have any UIViewControllers that observe NSNotifications, or otherwise might change their IBOutlets while they are off-screen? This is a common cause of this kind of crash. Make sure you're correctly memory managing your IBOutlets. UIViewControllers should never mess with their IBOutlets (or their UI components at all) when they are off screen. Even if you don't make this mistake, if you're not implementing things as noted in the above link, you can still crash after memory warnings.
MemoryWarning was a pretty good idea, and things have improved, but Apple still hasn't quite cooked all the issues around how it plays with UIViewController. The developer still needs to be very careful.
You should have your friend come to your computer and run it with NSZombieEnabled. That's the best way to debug these issues.
Ok so I've got a really annoying bug in my app. It's driving me crazy and I'm sure it's beyond my skill level as I am learning as I go.
Here is the initial rundown of the bug: A shot in the dark - Application bug
However I have found a way to consistently reproduce the bug (only on the device not in the simulator)
First you create a new Pool and save it. Then add 20 blank time entires into one day. Save it and this is where the problems begin. (when you go back to the main detail view the tableview has put itself out of editing mode with being told to do so). Now if you go back to the day to see the time entries you just added they are still there.
If you go back to the main overall tableview listing all pools and now go back to the day you added the times they have dissapeared.
Add one time and it all saves fine. Add twenty and it doesn't save. WTF!!
Main Menu listing Pools:
Detail view:
Edit View:
Time Edit View:
Add a time:
I'd appreciate any more guesses. But as well as this question I'm offering a bounty of £25 (Sorry I'm a poor student) to whoever is good enough to fix this bug first!
if your interested my email is danmorgz[at]gmail.com
Thanks,
Dan
If you haven't already done so, I'd recommend turning on NSZombie support and seeing if you're using any of your objects after they've been freed. As far as I know this can be turned on in the simulator and on the device.
Most likely, you're failing to retain some object somewhere along the way. When an object gets released and then the memory is re-used for something else, you'll get all sorts of bad behavior, including crashes, or mysterious "disappearance" of other objects.
One thing you can try is putting breakpoints into the -dealloc method of your custom classes. Then you can see where they're getting deallocated from. Most likely though, this will end up being when the AutoreleasePool gets drained, which won't tell you much.
Alternatively, look into using some of the memory debugging tools built into Cocoa.
That document is for Mac OS X, but I think most all of this will work in the iPhone simulator, at least. I know that your bug "doesn't happen" in the simulator, but that really only means that the symptoms are different, and you're not noticing them.
Thanks for all your answers. It's now fixed.
For those interested I'd forgotten to add a cellidentifer in the XIB of my cell subclass.
cellForRow: method was therefore creating a new cell every time. The memory got filled up very quick. It then seemed as though my app was automatically trying to cut the fat by forcing another tableView out of editing mode and not managing my instances properly.
Again it's a memory problem. Isn't this always the case!?!
The clue was a one off 101 error in the console indicating my app was using too much memory. Oh and a slow scrolling tableView.