Search code examples
iosobjective-cxcodedebuggingxcode5

Xcode won't step over crash


So, this has happened a number of times in a number of different projects. I'll be debugging my app in Xcode, when Xcode breaks on an error. After looking at it, I'd hit Step Over or Continue...and it wouldn't do anything. More accurately, it acted like it stepped, but didn't actually go anywhere. This can be repeated indefinitely, as far as I can tell. One reason this is problematic is that it never gives me the crash log, because it never finishes crashing. I only get the crash log when the app crashes and it isn't being debugged (which means I have to get it through Crittercism or by checking the device logs).

Anybody see this before, and/or know why it does this? I haven't seen any mention of this elsewhere, but it's happened to me in several projects.

For example, in one project we use SocketRocket, and every once in a while (for an as-of-yet unknown reason) it crashes in SRWebSocket.m in the following method:

- (void)main;
{
    @autoreleasepool {
        _runLoop = [NSRunLoop currentRunLoop];
        dispatch_group_leave(_waitGroup);

        NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate distantFuture] interval:0.0 target:nil selector:nil userInfo:nil repeats:NO];
        [_runLoop addTimer:timer forMode:NSDefaultRunLoopMode];

        int i = 0;

        while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) {
            NSLog(@"_runLoop %i %@", i++, [NSDate date]);
        }
        assert(NO);
    }
}

It crashes on the while line. (I added the NSLog line, by the way). When I hit Continue or Step Over, the line indicator flickers briefly, then appears again on the same line. Note that it does not continue to the NSLog line, and nothing is written to the console at all. I'm currently still trying to get it to crash again (this particular crash is rather unpredictable), but if I remember correctly, the line indicator says EXC_BAD_ACCESS, probably a prematurely deallocated object.


Solution

  • An ObjC out of range error will result in throw an ObjC exception, which ends up - if uncaught - in an abort. An abort really just raises a BSD signal (SIGKILL). That's easy for the debugger to pass on to the process so it can die naturally from it.

    EXC_BAD_ACCESS and EXC_BAD_INSTRUCTION are funny exceptions, since they first come in on the Mach side of the OS. To be properly propagated, they should be handled natively as Mach exceptions if there is a handler for them and if not, they should be passed to some system Handler, that turns them into the equivalent BSD exception (SIGSEGV) which will then be passed to the BSD signal handler and that will eventually cause your program to exit.

    There's a long-standing bug in the kernel interfaces afforded to the debugger that makes it impossible for the debugger to properly effect this little dance from the outside. So if you get an EXC_BAD_ACCESS, you're pretty much stuck there. For the most part, that doesn't much matter, your program was just going to turn around and die anyway. You wouldn't really gain any insight into your crash by watching it do that.

    It only matters if you have installed, and want to debug, a SIGSEGV handler. That has been hard on MacOS X for a decade or more. Fortunately, only a very few people actually need to do this...