Tracking down the source of bugs while writing code for any type of computer system can sometimes be one of the most interesting and challenging parts of developing software. It's almost like getting a really awesome puzzle book, but rather than having the answers listed somewhere towards the back, their spread across forum posts or SDK documentation, and in some of the more challenging cases just require you to wade off into the unknown, narrowing down the problem until you finally discover the one line that causing the entire thing to come crashing down.
After spending weeks or even months seeing bugs crop up and cause problems that seem to bare no resemblance to one another, you begin so see patterns forming, and rather than just seeing strange console messages and stack traces, you see the same errors cropping up again and again.
Over the next few weeks, I'm going to talk about some of the more frequently occurring bugs that I find in my code, useful tips I've discovered, and hopefully give any developers new to the iPhone scene, a slight head start.
Throughout the time I've been working with the iPhone SDK I've encountered many problems, some of which are one offs that you'd probably only ever need a fixx for once every blue moon, where as others occur more frequently (almost daily). The most major source of problems tends to stem from the way in which objective-c implements memory management. For those of you unfamiliar with how this works here is a quick rundown...
The most basic way to allocate memory for, and release objects is to use the alloc and release methods that will be inherited from the NSObject base class. Basically when we wish to allocate memory for an object we...
//Allocate memory for, and initialize the object
MyClass *aClass = [[MyClass alloc] init];
// When we are finished with the object we release it.
[aClass release];
the release method simply reduces the object reference count by 1. If this reference count reaches 0 then the objects dealloc method will be called, purging the object from memory.
Provided we always have matching pairs of alloc and release no memory should be leaked.
The second way of handling memory is to use Autorelease objects. Autorelease objects and convenience constructors are hugely useful when you only need to use a variable temporarily, or need to return an object from a method and need your code to take responsibility for the memory management. The only problem is there are loads of occasions where the pool memory containing my objects is released, and I find myself getting nil pointer exceptions, where my code is trying to message objects that don't exist any more. My remedy for this is to only use convenience constructors in confined blocks of code, where the object isn't likely to go out of scope and be released.
Now enter threading! If you use autorelease or convenience constructors in methods being run on other threads, make sure you initialise an NSAutoreleasePool at the beginning of your code block and release it at the end of your code block. This is because the default pool runs on the main thread only. If you don't do this you'll end up with memory leaking all over the place! Just keep an eye on the console as autorelease objects that have no pool will log messages warning you...
- (void)randomFunction
{
[self performSelectorInBackground:@selector(someMethod)];
}
- (void)someMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// ...
// Do some stuff here involving autoreleased objects.
// e.g.
// NSString *aString = [NSString string];
// NSData *someData = [NSData data];
// NSArray *myArray = [[[NSArray alloc] init] autorelease];
// ...
[pool release];
}
But remember that after releasing the pool you can't return any objects/values that were set to autorelease, although in most cases you won't be able to return objects anyway.
The majority of places I use this are in background syncing methods, or other blocks of code where literally tens, hundreds or even thousands of autorelease objects are created, and obviously if not dealt with properly, just float around taking up valuable resources.
Well thanks for reading guys, I hope this micro-rant has been of help. My next post will be all about singleton objects in Objective-c, and the best way to implement these.
Category Archive
-
- Add-ons4 posts
- api9 posts
- Design Discussion2 posts
- Events3 posts
- fixx30 posts
- fixx hacks4 posts
- General32 posts
- Hog Camp1 posts
- Hosted1 posts
- ISV1 posts
- Links4 posts
- News28 posts
- Opinion1 posts
- Product Updates3 posts
- Rails Plugins1 posts
- Rants8 posts
- solomon9 posts
- Tech Tips10 posts