Archive for September 2010

“self” is a four letter word

I don’t like to get strange memory crashes in my applications. So imagine my surprise today when I changed over some CFUUIDRef ivars to NSString, and as a result, I started getting some weird EXC_BAD_ACCESS messages.

For your perusal, consider listing A, where my class is being initialized with a nonatomic and retained property:

@synthesize nameString;
 
- (id)initWithData:(NSString *)inNameString
{
    self = [super init];
 
    if (self)
    {
        nameString = inNameString;
    }
 
    return self;
}

After awhile of beating my head against the wall, I changed it to look more like listing B:

@synthesize nameString;
 
- (id)initWithData:(NSString *)inNameString
{
    self = [super init];
 
    if (self)
    {
        self.nameString = inNameString;
    }
 
    return self;
}

I leave it to the reader to investigate this phenomenon. It is not too complicated, but if the subtlety is lost on you, there is always a memory based crash lurking around the corner.

Needless to say, if you are having strange memory crashes in your application, and your class looks like listing A, change it to look more like listing B. And if your app looks like listing B, it is working fine and you want to see how bad bad can really get, change it to look more like listing A.

EXC_BAD_ACCESS in a UIScrollView

After using my latest iPhone application on a device for a while, I was getting the following crash:

Program received signal:  “EXC_BAD_ACCESS”.
(gdb) backtrace
#0  0x33369ebc in objc_msgSend ()
#1  0x320e5248 in -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded] ()
#2  0x338b4a14 in -[NSObject performSelector:withObject:] ()
#3  0x320e5098 in -[UIAnimator stopAnimation:] ()
#4  0x320e4b7c in -[UIAnimator(Static) _advance:] ()
#5  0x320e4a34 in LCDHeartbeatCallback ()
#6  0x34350e60 in HeartbeatVBLCallback ()
#7  0x332e91c0 in IOMobileFramebufferNotifyFunc ()
#8  0x316532f8 in ?? ()
#9  0x33866b50 in __CFMachPortPerform ()
#10 0x338ae52a in CFRunLoopRunSpecific ()
#11 0x338adc1e in CFRunLoopRunInMode ()
#12 0x3434e1c8 in GSEventRunModal ()
#13 0x32002c30 in -[UIApplication _run] ()
#14 0x32001230 in UIApplicationMain ()
#15 0x00002ff8 in main (argc=1, argv=0x2ffff550) at /Developer/svn/MyCompany/iPhone/MyApplication/Other Sources/main.m:14

As you can see from the trace, the only mention of my code in there is the call to main.

I ran Build and Analyze from Xcode, and also set it up to run the clang analyzer on my project from the Terminal, and both of these did not find any problems in the code.

After using the NSZombieEnabled flag in the application, it came up with this message in the console:

2010-09-11 17:10:33.970 MyApplication[9321:207] ***
-[MyViewController respondsToSelector:]: message sent to deallocated instance 0x7489480

I think we finally tracked down a way to keep the error from occurring. I am guessing that the view was being deallocated and released while it was still undergoing a scroll animation. I changed my code to be like this:

[myTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:mainSection]
        animated:NO scrollPosition:UITableViewScrollPositionMiddle];

The application has not crashed with the same error since I changed all of these selectRowAtIndexPath calls to use the NO flag for the animated property. True, this does not fix the problem, but at this point, hiding it was good enough for me and our complaining customers.