Best procedure for dealing with memory warnings after losing opengl context - iphone

I've been chasing a bug in my game, I think i finally found the problem.
I have a memory management routine that gets called on memory warnings, it basically checks what is loaded and not needed, and releases that.
Most of my memory is being used in textures for opengl, such that besides textures I only need to dump a few objects to keep the system happy even on a 3G with it's limited memory.
Now my problem, on a few occasions I lose the openGL context, when playing a movie with MPMoviePlayerController for example, or when calling the GC system views.
A few times the loading of the GC or MPMovie will coincide with my memory management routine being called, this is what I think is crashing the game, since I don't have the opengl context, I get:
malloc: *** error for object 0x471c9080: pointer being freed was not allocated
when trying to glDeleteTextures.
Now I'm changing my code so I don't try to delete textures on an invalid context (still checking how to do that), but I'm still left with the problem of what to do when I get a memory warning during a opengl context blackout.
I see only one option
Before calling something that will make me lose context try and release memory
I don't particularly like this option because it introduces lag on some operations.
Anybody see a better way ?
Is my analisys of the problem correct ? (Do I really lose opengl context when using MPlayer and GC)
Any other way to release the textures ?
Thx

Well, it certainly sounds like there are at least a couple basic preventative steps you can take here:
You should keep a reference to your EAGLContext around. This will allow you to make your context current to operate on (delete) its textures at any time necessary. (You shouldn't be calling glDeleteTextures at some random time if you're not sure your context is current.)
You can check to see if your context is current with: if (myContext == [EAGLContext currentContext]).... You could choose to do no memory flushing when this is not true, or take other actions depending on its status.

Related

new in using XCode Instruments to interpret memory warning for iPhone development, guidance needed

I am working on an iPhone game which receives memory warning that I am not experienced enough to interpret. I have been watching some iTunesU tutorial but I am still not very good at this..
I have received various memory leaks whilst running my game and I wanted to understand how to interpret the stack trace show in Instruments properly.
I attach a screenshot of the ObjectAllocation instrument output . Even when I zoom filter I don't manage to filter the data in the ObjectSummary .
The peaks in memory usage in 1 happen when the GameScene is initialized and all the data is loaded (ParallaxBackground, CCSpriteBatchNode) and Sprites and bullets frames are created (in an CCArray of spriteFrames).
The big blue peak is just at load time but the app freezes and then crashes only after a while and from the graph I see that the memory usage (blue bar) has gone down.. so I don't quiet get that. Also, whenver I try to use the leaks instrument the App crashes..
I know is a very silly question for someone experienced, but I just need some extra help getting started with this toolset.
I think the memory problem are due to the sprites I allocate in sprite cache classes, but I am not sure on this and hence wanted to investigate this using Instruments but can't find out how to see what is the object causing the memory warning and how to access the stack trace..
PS: I am running on an iPod 4th generatio and I am using Cocos2D as library
EDIT: I do not also understand why if the Live Bytes are only 1.01 MB the App crashes and why I still receive a memory warning (see black flags). Is it due to some pointer referencing to some null variable or due to an excessive memory allocation? 1.01 MB doesn't seem much to me..
EDIT 2: Following Marion's advice I used the Activity Monitor and realized that the effective real memory usage is 55.39 MB. I misinterpreted the "live bytes" word. I will try to dig into this further and will leave the question as unaccepted for now to allow other people contribute. If I won't have any other answer within one-two days I'll mark as accepted the current answer. Thanks!
Thanks a lot!
If you want to find leaks, use Leaks instrument instead of Allocations. To find out, how much memory use at the moment, use ActivityMonitor.
If you will have problems with memory in cocos2d, you can try to purge cache. In cocos2d you can purge CCTextureCache, CCSpriteFrameCache, CCAnimationCache. It will release unused textures and frames.
If you want to check if all of unnessesary textures were removed from memory, you can place breakpoint to CCTextureCache class and call, for example, sharedTextureCache and look throw the content of textures_ dictionary. Or add some method to this class to be able to dump current state of cache.

cocos2d using gobs of memory

I'm having the absolute worst time with running out of memory in my game with cocos2d.
I have 4 scenes. two vanish from memory when I switch scenes using
[[CCDirector sharedDirector]replaceScene:sceneWithTransition]
I've tried push/pop and it makes the problem about 10x worse.
2 of the scenes however are like a virus. The conditions under which I can remove them from memory do not exist.
I am using the ARC alterations. I was hoping they would help, they did not.
I've overridden the cleanup method to make sure I get rid of references to everything in the scenes. The first one is the game play scene, and I can imagine how it might be possible that I've missed something that is somehow holding on to the scene. However the other one is the settings scene. It has 5 parts. they all get tossed and yet the scene will not purge. before converting to ARC the app was unusable it crashed so often and when it wasn't crashing it was running out of memory. After ARC it lasts about 4x longer than before but still runs out of memory regularly. Crashes however are almost non-existant.
I suppose first off, what is the correct way to switch between scenes?
Second, how does one remove something from memory when using arch because object = nil does nothing. All of my other programs using ARC run like dreams. None of them use the cocos2d engine. I'd not seen a memory error since the introduction of arc until I made the mistake of converting my quartz2d game in to cocos2d. The only reason I don't o back to a platform that actually functions is that I really like the effects possible in cocos that I simply cannot make work in quartz.
It seems that cocos2d had some issues with ARC that got fixed only recently.
I don't know if this has to do with your memory problems, but you might check which cocos2d version you are using.
Anyway, it seems that cocos2d will fully support ARC only from version 2.0. So, you might be better off not using ARC and getting your memory management right by properly using release. As far as I know, cocos2d has no memory problem, so you should be able to accomplish it.
push/pop from what I understand use a "stack" model thus memory is not erased when new scenes are pushed or popped, which would explain why that gets worse when using this method.
one way you can help save memory, especially during a transition, is to transition to a loading scene and then from there transition to the actual scene you want. This is because during a normal transition, both scenes occupy memory simultaneously for at least 1 frame, whereas a cheap loading scene will instead take each of their places, reducing the horrible memory spike that often occurs when transitioning between two intense scenes.

No memory leaks, yet still running out of memory?

In my cocos2d application I have run through it using instruments and removed all memory leaks. I have my game outputting how much memory is in use on the screen and it is constantly rising as the game progresses until I eventually run out of memory. The amount of objects on screen doesn't increase by very much each level. Its a fairly simple game so i should not be running out of memory so soon.
I am removing all objects from a level when it ends and reallocating new ones when a new level begins. Instruments tells me there are no memory leaks. When i run through instruments to show me where the allocations are the bulk of the problem doesn't seem to come from one place its all of my objects.
Any ideas what the issue might be?
Just because instruments doesn't show leaks, doesn't mean you're not still allocating memory you're not using. Pay attention to the ObjectAlloc graph and see if that is constantly rising without falling off.
If you allocate memory that you aren't using and can't clean up, that's just as bad as a leak, even though you haven't technically leaked anything because you've stashed some unused reference somewhere.
Look at how much memory you actually need to use or to keep for future use at any point in your app, then treat anything else previously allocated as a leak and fix it.
In Objective-C when using autorelease objects be wary of circular dependencies!
If you create object A and then an instance of object B and pass A to it, so that B retains A, and A also retains B (for example by adding it as child to A) you can easily setup a circular dependency and thus both objects won't be released.
Tip: add a -(void) dealloc method to all your scene classes, and set a breakpoint there. If you change a scene and its dealloc method isn't called after the scene transition has finished, you're leaking this scene (it's not released).
Try to find that leak by looking for a setup that's similar to the one I described above.
Be careful about autoreleased objects, since they are not released immediately. If you have sections with lots of allocations and autoreleasing, try using specific autorelease pools on them.
It happened to me when creating huge decision trees (using NSArrays) for a game AI.
A great way to check for objects that are aggregating in memory is to use Instruments' new (in Xcode 3.2.3) Heap Shot functionality.
Use the normal Allocations instrument against your running application. Perform a series of repetitive events that should come back to some known state (for example, go one level down in a navigation controller and come back). Every time you do this, click on the Mark Heap button in the left sidebar for the Allocations instrument (under the section heading Heapshot Analysis).
What this will do is mark the heap at each of the starting points for this repetitive action and compare the objects that have been created by that point with the objects that had been created by the time you marked the heap last. Only objects that have been created between those two points and are still alive in memory will be listed.
If you are accumulating objects, but they are either not leaks or are being missed by the Leaks tool, they should show up here. I've found a number of subtle memory buildups this way, particularly when you pair this with the UI Automation instrument to automate the repetitive actions you're testing.
The bulk of the problem seem to be that Sprites don't get released in cocos2d unless all actions have been stopped on those sprites. This is done using stopAllActions. Cheers for all the suggestions.

Memory crashes in iOS with real memory usage only at 5megs

I have been hunting down memory leaks for some time in my app. As of right now, as I flip back and forth between two views while watching the memory monitor instrument, the real memory fluctuates between 5 and 6 megs. This is all fine -- as far as I can tell everything is getting released properly when I pop back off a view. However, the virtual memory continues to increase and my available real memory drops rapidly every time I push the view back onto the view stack (even though the real memory usage of the app isn't increasing). Eventually, this all leads to an out of memory crash. Is this a telltale sign of any specific issue, or am I just missing a memory leak somewhere?
EDIT: The odd part is, I get an out of memory crash while the app is still only using up about 5 megs of real memory.
Do not use -retainCount.
The absolute retain count of an object is meaningless. It is an implementation detail. It may be influenced by many factors well beyond your code.
You should call release exactly same number of times that you caused the object to be retained. No less (unless you like leaks) and, certainly, no more (unless you like crashes).
See the Memory Management Guidelines for full details.
In this specific case, you are leaking memory but in a way that leaks can't find it. The objects that are leaked are still connected to your overall application's object graph somehow. Maybe through a notification, maybe through delegation, doesn't matter -- leaks sees the reference and concludes that the object might still be live.
Use the Allocations Instrument. Configure it to only track live allocations (since you don't care about objects that have been deallocated). Do some stuff with your app. Check out what Allocations knows about and explain why all those objects should stick around. You can use the data mining facilities to filter down to just your objects.
Anyway, you can also use the "Build -> Build and analyze" option to find suspicious non-conventional code.
Another reason why you may have memory lost in lower API layers is if you don't remove all your views from your view hierarchy (aka : not calling [view removeFromSuperview] everywhere). At least that's what seemed to have happened to me.
Note that most of time this isn't required, as you would simply release the main view and all its subviews, then rebuild it from the view controller when needed. Things start to get more tricky when you're not releasing the whole hierarchy but instead simply remove some of them from the hierarchy.
In that case, I came to the conclusion that you may have buffers or layers still cached in lower API parts, and in that case your Allocation instrument won't help you.
In order to monitor correctly you'll need to use the "Memory Monitor" (in System). You'll see that the "Physical Memory Free" line dropping close to 0 is the most reliable indicator that a Memory Warning will be issued.
Another advantage of using this instrument, is that you can attach it to a running process, thus making it possible to have console output and instrument running together easily.
Circular references also won't be counted in Leaks but you can track those in Allocations. Best bet is to fire up Allocations and get to a state where you think everything should be gone (or certain objects should be). If they're hanging around go dive in to them and look at where they've been retained and sort out the proper memory ownership/releasing.
As for Allocations, there are some things that it doesn't track that can affect the overall memory. Some of the things include some CGImage backing stores, some CoreAnimation stuff and some database stuff.
Have you used the "Leaks" Performance Tool? And check out the logs in Organizer to see if there's anything there.
Also look into the dealloc for the view controllers and make sure you are properly releasing all of it's objects?

My app closes without any warning or error message

I'm programming an puzzle game for iPhone using openGL.
There Is one very weird "bug" ( I'm not sure what It is)... whenever I touch the screen a great number of times in a short period of time my app closes, without giving a warning or error.
What could be the cause ?, I guess It has something to do with the memory, but I would like to know.
Edit:
I also think this happens because I'm calling multiple functions every time the user touches the screen or moves his fingers.
Sounds like you're running out of memory.
A few quick tips that might help out:
Check your memory profile over time using Instruments. If you see a steady incline over time, it's likely to be a memory leak, or an inefficient algorithm that is allocating more memory than you need.
Use a static analyzer to help check for leaks, such as Clang.
Images and image-related files are particularly memory-hungry, so focus on efficiency for them. When you work with textures in OpenGL, use the PVRTC format, which offers awesome compression.
didReceiveMemoryWarning: is your friend - aka a good chance to throw out anything you don't absolutely need in memory. Better to be memory-efficient the whole time, though.
Try setting up an NSUncaughtExceptionHandler. You may also want to setup a signal handler.