Zuerst ein Disclaimer. #NotMyCode.Noch ein Objective-C EXC_BAD_ACCESS
Der folgende Ausdruck delegate.deviceToken
löst manchmal eine schlechte Zeigerdereferenz aus, anscheinend aus 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
...
}
...
}
Die AppDelegate erklärt deviceToken
wie so:
@property (nonatomic, assign) NSString* deviceToken; // #NotMyCode
Quoth der Absturzbericht:
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)
Der Anruf an -[AppDelegate initializeWebServices]
kann aus dem AFNetworkReachabilityManager
Code, wie es in diesem Fall oder aus meinem application:didRegisterForRemoteNotificationsWithDeviceToken
herauskommt. Mein deviceToken
ist in der Tat nicht initialisiert in AppDelegate
, und so mit seiner assign
Semantik scheint es klar, dass ich versuche, Müll zu dereferenzieren. Aber wie verursacht der Null-Check einen Anruf an objc_retain
?
Es lohnt sich eindeutig zu versuchen, deviceToken
zu nil
zu initialisieren oder seine Speicherverwaltungssemantik zu aktualisieren. Bemerkenswert im Code sind auch ein paar Boolesche, deren Absicht der Schutz von Anrufen zu scheint, und die schlecht verwaltet werden können.
Aber ich habe keine Ahnung, wie diesen Fehler zu reproduzieren, und die App wird von Millionen jeden Monat verwendet. Ich bin sehr dankbar für alle Einsichten, die mir helfen, es in der nächsten Version richtig zu machen.
Wenn Sie sich auf deviceToken innerhalb eines Blocks beziehen, wird in der Tat ein Retain versucht, so dass der Wert von deviceToken während des Bereichs Ihres Blocks gültig ist. – nielsbot
Ihr Eigentum sollte "kopieren" oder "stark" sein, nicht "zuweisen" – dan
Auch wird der Null-Check hier nicht helfen, da Ihr Zeiger nicht Null ist. Es ist ein Zeiger auf ein nicht zugeordnetes Objekt. – nielsbot