Voici deux traces de pile de Crashlytics, les deux contenant la même ligne de mon code, mais aboutissant à deux crashs différents.iOS Crash sur la copie d'un NSArray EXC_BAD_ACCESS KERN_PROTECTION_FAILURE
# OS Version: 10.3.2 (14F90)
# Device: iPad 5
# RAM Free: 3.8%
# Disk Free: 90.7%
#0. Crashed: com.apple.main-thread
0 libsystem_platform.dylib 0x18d365090 _platform_memset + 126
1 libsystem_malloc.dylib 0x18d2ebd00 _nano_malloc_check_clear + 584
2 libsystem_malloc.dylib 0x18d2eacb0 nano_calloc + 80
3 libsystem_malloc.dylib 0x18d2dc4e8 malloc_zone_calloc + 168
4 libsystem_malloc.dylib 0x18d2dc41c calloc + 40
5 libobjc.A.dylib 0x18cd18160 class_createInstance + 76
6 CoreFoundation 0x18e2b2928 __CFAllocateObject + 28
7 CoreFoundation 0x18e29c064 +[__NSSingleObjectArrayI __new::] + 28
8 CoreFoundation 0x18e18cd18 -[NSArray initWithArray:range:copyItems:] + 400
9 MyApp 0x10010003c -[ConstituentDownload currentProgress] (ConstituentDownload.m:117)
10 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
11 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
12 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
13 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
14 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
15 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
16 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
17 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
18 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
19 MyApp 0x1001000b4 -[ConstituentDownload currentProgress] (ConstituentDownload.m:118)
20 MyApp 0x100100234 -[ConstituentDownload sendProgressNotification] (ConstituentDownload.m:141)
... button press stuff...
et:
# OS Version: 10.3.1 (14E304)
# Device: iPad 4
# RAM Free: 4.7%
# Disk Free: 12.2%
#0. Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x1bc38692 objc_retain + 1
1 CoreFoundation 0x1c8acf39 +[__NSArrayI __new:::] + 74
2 CoreFoundation 0x1c8ae9f1 -[__NSArrayM copyWithZone:] + 174
3 MyApp 0x189407 -[ConstituentDownload currentProgress] (ConstituentDownload.m:117)
4 MyApp 0x18999f -[ConstituentDownload userInfoForProgressNotification] (ConstituentDownload.m:180)
5 MyApp 0x189611 -[ConstituentDownload sendProgressNotification] (ConstituentDownload.m:144)
...button press stuff...
Et voici la méthode qui provoque l'accident:
- (float)currentProgress {
float sections = [self.childDownloads count] + 1;
float referencedProgress = 0.;
// This line causes the crash - where we copy the property array
for(ConstituentDownload *d in [self.childDownloads copy]) {
referencedProgress += d.currentProgress;
}
float progress = (super.currentProgress + referencedProgress)/sections;
return progress;
}
Le self.childDownloads
est un objet contenant NSMutableArray du même type que cette méthode réside dans: le ConstituentDownload
. Il est accédé à partir d'autres threads et peut avoir des éléments ajoutés, c'est pourquoi je le copie d'abord avant de le parcourir. Ce tableau a tendance à contenir 0-20 objets.
Ce blocage peut-il être causé par la mutation du tableau dans un thread différent, même si je le copie ici?
Cela peut-il être causé par une sorte de corruption de la mémoire? Si oui, pouvez-vous me diriger dans la bonne direction pour comprendre cela?
Cela peut-il être dû au fait qu'il n'y a plus de RAM sur l'appareil? Si oui, pourquoi cela n'aurait-il pas été signalé comme une erreur de mémoire au lieu de générer un rapport d'erreur?
Oui, cette méthode est récursive, dans un sens. Le parent ConstituentDownload
appelle currentProgress
sur chacun de ses téléchargements enfants, qui à son tour l'appellent sur chacun de leurs téléchargements enfants. La pile de crash a parfois seulement 1 appel récursif, et parfois environ 10, comme on le voit dans ces deux piles de crash.
Ce plantage n'a été observé que sur les appareils exécutant iOS 9 et iOS 10, mais probablement parce que presque tous mes utilisateurs utilisent ces deux versions du système d'exploitation.
Que signifie KERN_PROTECTION_FAILURE de toute façon?