user3570727
user3570727

Reputation: 10213

Stomped on a "EXC_BAD_ACCESS KERN_INVALID_ADDRESS" for a block handler

I have production code which I see that it crashes once in a while with a EXC_BAD_ACCESS KERN_INVALID_ADDRESS on the block handler. I could for the life of me figure out what is wrong with my code. I have tried to reproduce this and could not in my controlled environment. Here is the stripped out and cleaned up code :

Code Snippet :

typedef void (^TestCallBackHandler)(NSString* location, NSError* error);

@interface _TestClass : NSObject

@property (nonatomic, copy) TestCallBackHandler handler;
@property (nonatomic, strong)NSTimer *endTimer;

- (void)fireOneOff:(TestCallBackHandler)handler;

@end

@implementation _TestClass

- (void)fireOneOff:(TestCallBackHandler)handler
{
    _handler = handler;

    NSLog(@"** New %p %@ Incoming %p, %@ Ours %p %@",self,self,handler, handler, _handler, _handler);
    _endTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(_stop) userInfo:nil repeats:NO];
}

- (void)dealloc
{
    NSLog(@"%@ Dealloced",self);
    _handler = nil;
}

- (void)_stop
{
    NSLog(@"** Stopping ? %@",self);
    if (_handler)
        _handler([NSString stringWithFormat:@"Hello %@",[NSDate date]], nil);
}

@end

The calling code in my class is defined as :

@property (nonatomic, strong)_TestClass *testClassInstance;

and called like this :

- (void)startTestClass {
    _testClassInstance =  [[_TestClass alloc] init];
    [_testClassInstance fireOneOff:^(NSString *newString, NSError *error) {
    NSLog(@"Got new String! %@",newString);
    _testClassInstance = nil;
}];
}

Few things to note :

Any pointers, help highly appreciated.. I just cant put a finger in this code and say that is what is wrong. Please help!

Upvotes: 1

Views: 1003

Answers (2)

Sebastian K
Sebastian K

Reputation: 186

If you want to have more information about EXC_BAD_ACCESS, then you can turn of NSZombies. In Xcode go to Product > Scheme > Edit Scheme and set checked Enable Zombie Objects.

Upvotes: 1

ben
ben

Reputation: 890

Two hints which occur a little bit strange to me:

First: why are you setting the object to nil in it's own block.

- (void)startTestClass {
        _testClassInstance =  [[_TestClass alloc] init];
        [_testClassInstance fireOneOff:^(NSString *newString, NSError *error) {
        NSLog(@"Got new String! %@",newString);
        _testClassInstance = nil;
    }];
}

Second your object may be released already and the NSTimer is trying to execute a method on a release object

- (void)fireOneOff:(TestCallBackHandler)handler
{
    _handler = handler;

    NSLog(@"** New %p %@ Incoming %p, %@ Ours %p %@",self,self,handler, handler, _handler, _handler);
    _endTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(_stop) userInfo:nil repeats:NO];
}

I also dont get what the code does exactly and why. I believe there would be an easier and better maintainable solution for what you are achieving in this class.

Upvotes: 1

Related Questions