Reputation: 10213
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
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
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