I thought that I was really close to release this new App of mine when I ran into a dead end. My code works without memory leaks in the simulator (Xcode 4.0.2) but reports memory leaks on my devices.
I think my issue is related to that I copy an object, because in my troubleshooting attempts I tried without a copy, and then the memory leak goes away (but of course so do my functionality!).
What I do is that I add a number of instances of a subclass of UIView to an array . This subclass(Cities of which cityToAdd is an instance) has two UIViews and some variables that I need to access at a later stage.
If I do this I get memory leaks on my devices:
[arrayOfCities addObject:[[cityToAdd mutableCopy] autorelease]];
But if I do this I don't (but loose functionality)
[arrayOfCities addObject:cityToAdd];
In the subclass I have this to handle the copying:
- (id)mutableCopyWithZone:(NSZone *)zone{
Cities *newCity = [[Cities allocWithZone:zone] init];
[newCity initWithCityName:cityName
onRing:ring
withTimeZone:timeZone
withTimeZoneOffset:timeZoneOffset
withDSTAngle:DSTAngle
andDST:isDST];
return newCity;
}
From Instruments I get this when testing on a device:
and when I drill down on the second row it shows this:
Finally my initWithCityName method (sorry for such a long post!!) I put it as a picture to get the colors and messages from Instruments...
Finally the UIIMage imageNamedUniversal is an extension to give me #2x images on the iPad (but I have tried with the normal imageNamed and get the same memory leaks).
I dont know where to start!! Appreciate any ideas.
Thanks
Why are you calling two initialization methods? You are calling init and initWithCityName....
Two things to consider:
After you add cityView and DSTView as subviews, you can and should release them.
And you are initializing newCity twice in your copyWithZone.
Thanks for fast replies and suggestions. You got me on the right track. The cityToAdd that I added to my array was added several times in a loop, but I kept the alloc and init outside of the loop. Once I moved it inside the loop it works in both simulator and device.
Weird that the simulator don't report that memory leak though...
Again, thanks for your fast replies!
Related
Good Day,
I'm completely inexperienced in checking for memory leaks and so any help with this would be great.
I've just finished the bulk of the work for my iPhone app and I'm now trying to figure out why it stops working after a couple of runs. Using Instruments in Leaks and Allocations mode I can see there are two objects that are piling up memory quite quickly and not releasing:
I'm not a hundred percent sure where or why this is happening, but when I clicked on the arrow to the right of UIDeviceRGBColor the Responsible Caller is stated as
[UIColor allocWithZone];
I did a search through my project for UIColor and came up this (take note of _colorThreshold):
I believe my problem has to do with _colorThreshold which doesn't seem to be getting released:
I've tried adding autorelease to their initialisation arguments, but that made the app crash. Any advice here?
EDIT 1
Here is the screen shot from LevelMeter.h
There are several issues with the above:
Is LevelMeterColorThreshold an Objective-C class?
If so, why are you using malloc instead of the usual alloc/init?
As you pasted screenshots of your search results, we cannot see the surrounding code, as only lines with search hits are displayed.
Does the Leaks instrument report leaks, or are you just allocating unnecessary memory?
There is a difference between those two cases:
A leak happens if you loose reference to an object so that you cannot send it a release message later.
Instantiating objects, that aren't needed anymore without releasing/freeing them
Leaks can only detect the first case.
Sample for a leak:
NSMutableString* test = [[NSMutableString alloc] initWithString:#"1"];
NSLog(#"%#", test);
NSMutableString* anotherTest = [[NSMutableString alloc] initWithString:#"2"];
test = anotherTest; //here we loose reference to the original object
NSLog(#"%#", test);
By assigning anotherTest to test, we have lost the reference that points to the memory address that contains #"1".
In my iOS OBJC app, i use a object, specifically a UIImage. I always need this UIImage, specially when the user decides to switch orientations. The problem is I only get this image once and will need it for as long as the app runs. As a result, I have allocted this object and sent it a retain. I never release it, because if I do and the user switches orientation, that object could be realsed and I won't be able to do what I need to do and as a result the app will crash.
My Point: What do I do? Is what I'm doing bad because it creates a leak? And if so, how can I fix this?
Thanks.
It sounds like you're loading a single image once and keeping it around to reuse forever. That is perfectly fine, although if it's a large image that might not be needed constantly you might want to listen for memory notifications and release it then.
Problems with never releasing come in when you allocate large objects or large numbers of objects that are never released. Particularly if you continually re-allocate new instances of the "same" thing because you lose track of the old ones.
John. I have a different approach, load and release everywhere. You see, when you use [UIImage imageNamed:] then iOS caches the image. Next time you call [UIImage imageNamed:], it uses the cached image, from memory, very quickly. That way you can still code for clean memory (release all over the place, no retain) and iOS has your back.
I have a navigation based App with 5 ViewControllers. After inspecting the memory allocation with instruments i found out that memory is increasing permanently. The app starts up with 2 MB and after navigating through all 5 Navigationcontrollers it grows up to 10 MB and counting...
For every allocated object there is a corresponding release in my code (in dealloc or somewhere else), so obviously there are no memory leaks. Instruments also tells me that no memory leaks could be found.
How can I solve this memory problem? At some point of time, after navigating through the views forward and backward an out of memory warning occurs and the background image disappears (I do not deallocate the image so the iphone does it on its own).
How can i determine the source of the "memory leak" problem? Is it possible that images are cached somewhere and hold in memory as long as the app is alive?
I always alloc images like this:
UIImage *kaufpreisImage = [[UIImage alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource:#"kaufpreis_background_green18px" ofType:#"png"]];
The images are under the Resource folder.
I would very much appreciate your help! I can't find a way out of this!
Thank you very much in advance
Regards Phil
Edit:
The only problem remaining is when I try to send an email. I want to send an email which contains multiple html tables and images inside the email body. The images are base64 encoded. After sending multiple mails I recieve an out of memory warning, although I dealloc all the stuff (images, Numbers and so on) inside the sendMail() method.
Does anyone know if sending base64 encoded images leads to problems? Can anyone give me a hint how I can send images inside the emailbody (e.g. as background image inside a html table like style="background-url(data:image/png;base64,%#)")? To clearify, this works. The images are sent to the Client (tested on MacOS) but sometimes the memory problem occurs...
Thank you very much
You need to release those images once you take ownership of them.
Maybe you shall try the 'Heapshot' function in the Allocation tool. Simply take a 'Mark Heap' when your first controller is started then navigate on and again back. Take another heapshot. Repeat this process 8-10 times. In the heapshots list you shall see that some memory has been allocated between an heapshot and the following one (otherwise if the amount is small and tends to zero it is normal), try to inspect it in order to check if you allocate something that remains alive.
You are responsible for releasing the instances of UIImage if you have used [[UIImage alloc] init...] to create them.
If you are loading images from the main bundle, try using +(UIImage *)imageNamed:(NSString *)name. This UIImage returned is returned autoreleased, so you don't have to release, and there is the upside that UIKit handles caching when using the imageNamed method.
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.
My GUI for an iPhone app uses numerous UIViews. The user "flips" through these views when they tap a button to go forward or backward. The views are stored offscreen and are added to an actual view only when the program needs to display it.
During the flip process, the program tells the parent view (a uiscrollview) to remove any existing subview using the removeFromSuperView method, and then adds the new subview, which is the new page that the user should see.
However, after several repeats of this process on the device, the program crashes with gdb exit status 101, which I found is caused by an out of memory error.
I tried diagnosing this problem using the Leaks tool, but to no avail. There is only 1 or 2 small memory leaks and the total mem usage on the device by the program is only 2.5 mb. Is it possible that video memory, not system memory, is running low?
I came across this post regarding backgroundColor and mem usage, but I need further explanation. Should I reduce setting the backgroundColor to prevent the UIView's CALayer from hogging too much memory?
Do you have access to the iphone sample code on apple? Sounds like the PageControl Sample Code program is a good example of what you're looking for. And the sample code programs don't have memory leaks or any such problem :) Link here
When you were using instruments, did you check the ObjectAllocations? I've found that to be more useful than the leaks tool (object allocations is one of the tools leaks includes though). I would think that if video memory were running out it would be a different error, but I could be wrong.
Where are you storing all these views? Specifically, do you have some array (NSArray) that has these views when you flip through them?
The views won't get deallocated unless their reference count goes to zero. Your `[[UIView alloc] init] makes the reference count at 1, adding it as a subview makes it 2, and removing it from a subview makes it 1 again. Seeing as you don't get told of a specific leak, it seems that you're not really leaking as much as storing it somewhere.