A Few Lessons Learned

I fixed my memory stomp bug this morning. In doing so I learned a few important lessons:

  • It’s important to walk away from frustrating problems. I don’t know why I keep having to relearn this lesson. Hell, it’s even advice I give to other people. Most of the time I do it, but sometimes I find it hard to walk away from a problem. In this case, getting away from the problem and sleeping on it allowed me to come back to it with fresh eyes this morning and fix it.
  • Sometimes the iPhone simulator is a great debugging tool. I do most of my development and debugging directly on my iPod touch. There are slight performance differences with the way OpenGL behaves on the simulator vs the devices, so I figure it’s better to run it on the device when possible. However, the simulator has a few advantages. One advantage is that you can execute your iPhone app with “Enable Guard Malloc” turned on in your XCode “Run” menu. (Note: This does not work when debugging on a device. Only in the simulator.) This is the functionality that found my memory stomp. It’s amazing! It’s puts strict memory guards around blocks of memory every time they’re allocated. Once a block of memory has been freed, if anything else tries to write to that memory, it throws a Bad Access error. This allowed me to catch some of my code doing something really stupid.
  • Never delete Object A from inside a callback from Object A, especially when Object A still has work to do. This seems like an obvious thing, but when you get into animation systems and callbacks, sometimes it’s not obvious that you’re doing it. This turned out to be my problem.

To elaborate, yesterday I tried putting some new loading screens into the game. Of course, I didn’t want a loading screen to just appear, so I put a couple of animations into the various game modes that allow the loading screen to fade in and fade out as you exit and enter a new game mode (note: I treat the front-end as a game mode for these purposes). The problem was, I was using the animation callback to trigger the change between game modes. When the fade in completed, I would tell the game to throw away the current mode and load the next mode. The problem was, in throwing away the current mode, I was killing the animation manager. However, upon returning from the callback, the animation manager would try to do some animation cleanup on the animation that just finished, but none of the animation manager existed anymore, so it would start mucking around with member variables that didn’t exist anymore. This would result in all kinds of nasty behaviour.

So, the solution: when the fade animation completes, it sets a flag in the game mode that says “on next update make the transition to the new game mode”. This allows the animation manager to do it’s clean up before it gets killed. It’s kind of messy, but what can ya do.

One more thing: this whole mess got noticed because I still have a breakpoint set inside “malloc_error_break“. If you’re doing iPhone development, you should always have a breakpoint set in there. It will help you catch so many memory issues. It’s helped me catch double-frees in the past, and a memory stomp this time. This time it gave me this error: “malloc: *** error for object 0x16330c: Non-aligned pointer being freed” This doesn’t look like a memory stomp error, but by default malloc allocates everything to 16-byte alignment on the device, so when the system tries to free something that’s not aligned, it usually means something’s stomped it. Good to know!

Feeling good having fixed that problem. I also had a good sleep last night, the first one in a while, so I’m feeling good. Onward and upward!

Owen

2 Responses to “A Few Lessons Learned”

  1. Noel says:

    Wait, so by default, in debug mode, Xcode won’t stop your program in the debugger in case of a double free??? Wow! I just confirmed that. That seems weird that that’s not the default behavior. Thanks for the tip!

    Fortunately, I’m doing hardly any allocations at runtime, so I’m pretty safe, but still… Scary stuff.

  2. OG says:

    Yeah, I was shocked when I discovered that too. Now I always have a breakpoint set in malloc_error_break to catch problems as soon as they happen.

Leave a Reply