Feb 19

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.

Tagged with:
Jul 11

I have been trying to be a good code citizen and make sure all data I create is released and I don’t cause any memory leaks. I found that I was doing a lot of the following:

NSLog([NSString stringWithFormat:@"Class Name: %@", [object class]]);

Therefore, I didn’t have a reference to the object that I created, and couldn’t explicitly release it. This sort of code convention is just from my Java background, and the fact that I’m used to local method variables to be created on the stack. Since, Obj-C likes to create objects on the heap, you can’t rely on anything going out of scope and getting chewed up (doesn’t have Garbage Collection (at least in the iPhone API)).

After debating it a bit, I learned that “stringWithFormat” returns an NSString that is set to autorelease. That’s great, takes care of my problem. When the event handling loop completes all the string will be released, and all is well. But, there is still one thing bothering me. Here is the documentation for “stringWithFormat”:

XcodeScreenSnapz006

Nowhere does it say the returned string is set to be autoreleased.

In, Session 3 of the Stanford Lectures, Evan Doll states that Method names give you the answer:

Method Names & Autorelease
•Methods whose names includes alloc or copy return a retained object that the caller needs to release
•All other methods return autoreleased objects
•This is a convention- follow it in methods you define!

NSMutableString *string = [[NSMutableString alloc] init];  // We are responsible for calling -release or -autorelease
[string autorelease];
NSMutableString *string = [NSMutableString string];
// The method name doesn’t indicate that we need to release it
// So don’t- we’re cool!

So, there’s the answer. Based on the name of the method, I should know if that object is set to be autoreleased or not. But doesn’t this strike anyone as particularly dangerous? As a developer I am at the mercy of a 3rd Party API developer to follow convention properly. In my mind, this should be documented and done so using any auto-documentation facilities that Xcode has (don’t actually know if it has any).

Tagged with:
preload preload preload