Search code examples
iphoneobjective-ciosalloc

Objective C: [MyObject alloc] now crashes under iOS SDK 4.1


I'm working on an existing, large-ish codebase, and after upgrading the iOS SDK to 4.1 I am now seeing very strange behaviour. The crux of the matter appears to be a particular class that will no longer alloc - it is throwing a bad access in obj_msgSend, and seems to be the Class object on the stack that objc_msgSend doesn't like - although it is not actually NULL.

The original failing line looked like this:-

tileProjection = [[RMFractalTileProjection alloc] initFromProjection:proj tileSideLength:sideLength maxZoom:18];

I deconstructed this to isolate the problem:-

RMFractalTileProjection *p = [RMFractalTileProjection alloc];  // <- this crashes
p = [p initFromProjection:proj tileSideLength:sideLength maxZoom:18];
tileProjection = p;

I then tried this:-

Class c = NSClassFromString(@"RMFractalTileProjection");
assert(c);
NSLog( @"RMFractalTileProjection class(ptr) %p", c );  // <- prints an address OK
NSLog( @"RMFractalTileProjection class(obj) %@", c );  // <- crashes

In the debugger it looks like the Class object is sensible, but NSLog crashes when it tries to print it.

One thing to note: the class in question is declared as below, and I'm not sure if the protocol is causing a problem. Because this particular part is a large chunk of open source code, it is very difficult to remove this protocol requirement to see if that makes a difference.

@interface RMFractalTileProjection : NSObject<RMMercatorToTileProjection>
{
 ...
}

Any help on this one greatly appreciated - it is a show stopper.

Thanks


Solution

  • OK, finally found this. As Jeremy suggested, this turned out to be a regular memory stomper.

    The difficulty I had finding it was that it wasn't the Class object itself that was getting stomped, but the class' metaclass structure - which is a normal Class object but one level up, referenced by the class 'isa' pointer. That's why the class looked OK to me when I inspected it in the debugger - I need to follow the isa pointer and dump memory at one level up to find this. Luckily for me, the class was only a subclass of NSObject - had it been deeply subclassed, this could have been much harder to find. I got my first clue after biting the bullet, reverse-engineering objc_msgSend, working out exactly what was on the stack frame, and following all the pointers. Yep, the hard way :)

    Matt Gallaghar's post (and various others I found by following links) were invaluable in helping me through this maze - thanks guys!

    Burned a lot of time on this one, but on the up side I learned a hell of a lot about Objective C internals during the past day and a half :)