QED
QED

Reputation: 9923

Objective-C EXC_BAD_ACCESS with assign object property

The delegate.deviceToken expression below sometimes throws a bad pointer dereference, apparently out of objc_retain().

MyWebServices.m:

@implementation MyWebServices

+ (void)initializeWithCompletionBlock:(void (^) (id data))completionBlock withErrorBlock:(void (^)(NSError* error))errorBlock {
    AppDelegate* delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];

    if (delegate.deviceToken == nil) { // MyWebServices.m:29
       ...
    }

    ...

}

The AppDelegate declares deviceToken like so:

@property (nonatomic, assign) NSString* deviceToken; // #NotMyCode

Quoth the crash report:

Code Type:           ARM-64 (Native)

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000f434c4388
Triggered by Thread:  0

0   libobjc.A.dylib                     0x0000000180a940b0 objc_retain + 16 (objc-object.h:341)
1   MyApp                               0x0000000100054f98 +[MyWebServices initializeWithCompletionBlock:withErrorBlock:] + 200 (MyWebServices.m:29)
2   MyApp                               0x000000010003b97c -[AppDelegate initializeWebServices] + 224 (AppDelegate.m:380)
3   MyApp                               0x00000001000b123c __47-[AFNetworkReachabilityManager startMonitoring]_block_invoke + 132 (AFNetworkReachabilityManager.m:199)

The call to -[AppDelegate initializeWebServices] can come out of the AFNetworkReachabilityManager code, as it does in this case, or out of my application:didRegisterForRemoteNotificationsWithDeviceToken. My deviceToken is indeed not initialized in AppDelegate, and so with it's assign semantics it seems clear that I am trying to dereference garbage. But how does the nil check cause a call to objc_retain?

Clearly it's worth trying to initialize deviceToken to nil, or update its memory management semantics. Also noteworthy in the code are a few booleans, the intent of which seems to be the protection of calls to initializeWebServices, and which may be managed poorly.

But I have no idea how to reproduce this bug.

Upvotes: 4

Views: 1359

Answers (1)

trojanfoe
trojanfoe

Reputation: 122401

The property is mis-declared; it should use the strong or copy attribute instead of assign:

@property (nonatomic, strong) NSString* deviceToken; 

Using assign means the object is not being retained correctly, hence the exception.

Upvotes: 4

Related Questions