Ah, the most dreaded error. Your app crashes unexpectedly and the only output you have is EXC_BAD_ACCESS. Not a lot of information, and for someone from a Java or other higher level language background it can be very frustrating to track down. First of all, make sure you are running in debug mode always (even if you don’t have any breakpoints). This will give you a stack trace of what generated the EXC_BAD_ACCESS. Again, this may not actually tell you where the problem lies, because all EXC_BAD_ACCESS is telling you is that you are attempting to reference a pointer that is no longer valid. Therefore, at some point previous (unknown where or when) you blew away a pointer you shouldn’t have. Here are the three most common (in my case, at least) causes for these, and how to help mitigate or track them down.
Over Release – You’ve released an object, its retain count has gone to 0 and you try to access it. This is probably the most common thing that bites you when first starting out with Objective-C while learning how to manage memory. The stack trace will at least given you an idea of what object is over released (it may be an object owned by the one pointed to in the stack trace), and if you have designed your code well, encapsulation should keep you from having too many places to check. And trust me, encapsulation is key to minimizing the pain here, if you are throwing references around all over the place retaining and releasing, you are in for a world of hurt.
Once you have all the places that retain/release occur for that object, just make sure you have a one to one ratio. Apple provides a great Memory Management Document and is highly recommended. Pretty much, the gist of calling release is do it ONLY if you call retain, alloc or copy. That simple (but still easy to forget).
dealloc – This is one that bit me, and took awhile to track down. When you override dealloc on an object, remember to call [super dealloc] as this cleans up the object up the chain until it reaches NSObject and does the low level cleanup. When overriding, you need to release any objects you are managing as well. However, my biggest lesson learned here, is calling [super dealloc] LAST. I had called [super dealloc] before releasing my objects and started getting EXC_BAD_ACCESS errors. So, I spent multiple hours trying to track down a retain/releases inconsistency. Until finally realizing, that by calling [super dealloc] before cleaning up my objects, I had lost my reference to those objects.
stringWithFormat – If your stack trace is pointing to a bit of code where you are constructing a NSString via stringWithFormat, confirm that you are not trying to send a primitive (int, float, BOOL, etc) to %@. The runtime is attempting to access memory at a location of the primitive’s value. Let’s just say, I’ve done this more than once.
Those are the top three items that cause me grief with a EXC_BAD_ACCESS and the first three things I check when it appears.