I'm seeing a lot of crashes in an app in the app store which I'm totally unable to reproduce or speculate from code review what the cause could be. What is particularly confusing is that this is occurring at app launch while there is low memory - confusing because if there was insufficient memory for the app to launch I might expect to see other types of crash reports as opposed to an EXC_BAD_ACCESS - i.e. if the EXC_BAD_ACCESS is being caused by accessing deleted memory, there's nowhere in the code where anything gets the chance to be deleted, as the crash is occurring as objects are in the process of being created.
I've tried many thing to recreate this - running in the simulator and sending low memory warning messages, deliberately failing the initialization of various objects in the app creation process, calling calloc during app launch to consume vast amounts of memory, running the app numerous times on a handset whose RAM is totally maxed out. I can't recreate, or see from code inspection what might be going wrong.
Here is a crash report:
Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype:
KERN_INVALID_ADDRESS at 0x0000000000000000 **(many also at 0x0000000000000008)**
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 The_Name_Of_MyApp 0x000000010268ca94 SearchViewController.init(coder:) + 838292 (SearchViewController.swift:67)
1 The_Name_Of_MyApp 0x000000010268ca88 SearchViewController.init(coder:) + 838280 (SearchViewController.swift:67)
2 The_Name_Of_MyApp 0x000000010268cd4c @objc SearchViewController.init(coder:) + 838988 (SearchViewController.swift:0)
3 UIKitCore 0x00000001bca63d64 -[UIClassSwapper initWithCoder:] + 248
4 UIFoundation 0x000000019a77fe88 UINibDecoderDecodeObjectForValue + 744
5 UIFoundation 0x000000019a7800cc UINibDecoderDecodeObjectForValue + 1324
6 UIFoundation 0x000000019a71eb3c -[UINibDecoder decodeObjectForKey:] + 320
7 UIKitCore 0x00000001bd0a1288 -[UIViewController initWithCoder:] + 1420
8 UIKitCore 0x00000001bceb5dcc -[UITabBarController initWithCoder:] + 80
9 The_Name_Of_MyApp 0x000000010283f658 TabBarViewController.init(coder:) + 2618968 (TabBarViewController.swift:0)
10 The_Name_Of_MyApp 0x000000010283f70c @objc TabBarViewController.init(coder:) + 2619148 (TabBarViewController.swift:0)
11 UIKitCore 0x00000001bca63d64 -[UIClassSwapper initWithCoder:] + 248
12 UIFoundation 0x000000019a77fe88 UINibDecoderDecodeObjectForValue + 744
13 UIFoundation 0x000000019a71eb3c -[UINibDecoder decodeObjectForKey:] + 320
14 UIKitCore 0x00000001bcd9dcbc -[UIRuntimeConnection initWithCoder:] + 188
15 UIFoundation 0x000000019a77fe88 UINibDecoderDecodeObjectForValue + 744
16 UIFoundation 0x000000019a7800cc UINibDecoderDecodeObjectForValue + 1324
17 UIFoundation 0x000000019a71eb3c -[UINibDecoder decodeObjectForKey:] + 320
18 UIKitCore 0x00000001bccc4a1c -[UINib instantiateWithOwner:options:] + 1124
19 UIKitCore 0x00000001bce92f18 -[UIStoryboard instantiateViewControllerWithIdentifier:] + 196
20 The_Name_Of_MyApp 0x000000010266b4dc InitialViewController.start() + 701660 (InitialViewController.swift:118)
21 The_Name_Of_MyApp 0x000000010266bba4 @objc InitialViewController.start() + 703396 (InitialViewController.swift:0)
22 Foundation 0x0000000190bff6d0 __NSFireDelayedPerform + 404
23 CoreFoundation 0x00000001900f2bf0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 28
24 CoreFoundation 0x00000001900f2920 __CFRunLoopDoTimer +864
25 CoreFoundation 0x00000001900f2154 __CFRunLoopDoTimers + 248
26 CoreFoundation 0x00000001900ed030 __CFRunLoopRun + 1880
27 CoreFoundation 0x00000001900ec5b8 CFRunLoopRunSpecific + 436
28 GraphicsServices 0x0000000192360584 GSEventRunModal + 100
29 UIKitCore 0x00000001bc9e3558 UIApplicationMain + 212
30 The_Name_Of_MyApp 0x00000001026ea6b0 main + 1222320 (AppDelegate.swift:20)
31 libdyld.dylib 0x000000018fbacb94 start + 4
Thread 1:
0 libsystem_pthread.dylib 0x000000018fd80cfc start_wqthread + 0
Thread 2 name: Dispatch queue: com.myQueue.backgroundSerialQueue
Thread 2:
0 libsystem_c.dylib 0x000000018fc60ae4 __v2printf + 616
1 libsystem_c.dylib 0x000000018fc60a00 __v2printf + 388
2 libsystem_c.dylib 0x000000018fc46ac0 _vsnprintf + 264
3 libsystem_c.dylib 0x000000018fc3b9c0 snprintf_l + 28
4 CoreFoundation 0x000000019010fa88 __CFStringAppendFormatCore + 8548
5 CoreFoundation 0x00000001901111b8 _CFStringCreateWithFormatAndArgumentsAux2 + 136
6 Foundation 0x0000000190afd3ec -[NSString initWithFormat:locale:] + 36
7 Foundation 0x0000000190afd364 -[NSNumber descriptionWithLocale:] + 1044
8 CoreFoundation 0x000000019004d9a8 -[__NSCFNumber descriptionWithLocale:] + 72
9 CoreFoundation 0x0000000190053268 -[__NSCFNumber stringValue] + 64
10 The_Name_Of_MyApp 0x00000001025f6494 -[RobocallerManager readCityAndStateData] + 222356 (RobocallerManager.m:596)
11 The_Name_Of_MyApp 0x00000001025f343c __25-[RobocallerManager init]_block_invoke + 209980 (RobocallerManager.m:148)
12 libdispatch.dylib 0x000000018fb9b6c8 _dispatch_call_block_and_release + 24
13 libdispatch.dylib 0x000000018fb9c484 _dispatch_client_callout + 16
14 libdispatch.dylib 0x000000018fb43c18 _dispatch_lane_serial_drain$VARIANT$mp + 592
15 libdispatch.dylib 0x000000018fb44760 _dispatch_lane_invoke$VARIANT$mp + 432
16 libdispatch.dylib 0x000000018fb4cf00 _dispatch_workloop_worker_thread + 600
17 libsystem_pthread.dylib 0x000000018fd7e0f0 _pthread_wqthread + 312
18 libsystem_pthread.dylib 0x000000018fd80d00 start_wqthread + 4
Thread 3:
0 libsystem_pthread.dylib 0x000000018fd80cfc start_wqthread + 0
Thread 4 name: com.apple.uikit.eventfetch-thread
Thread 4:
0 libsystem_kernel.dylib 0x000000018fceded0 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x000000018fced3a8 mach_msg + 72
2 CoreFoundation 0x00000001900f1fb0 __CFRunLoopServiceMachPort + 236
3 CoreFoundation 0x00000001900ece4c __CFRunLoopRun + 1396
4 CoreFoundation 0x00000001900ec5b8 CFRunLoopRunSpecific + 436
5 Foundation 0x0000000190ae06a4 -[NSRunLoop+ 34468 (NSRunLoop) runMode:beforeDate:] + 300
6 Foundation 0x0000000190ae0514 -[NSRunLoop+ 34068 (NSRunLoop) runUntilDate:] + 88
7 UIKitCore 0x00000001bc940ac0 -[UIEventFetcher threadMain] + 136
8 Foundation 0x0000000190c133b0 __NSThread__start__ + 1040
9 libsystem_pthread.dylib 0x000000018fd7d2fc _pthread_body + 128
10 libsystem_pthread.dylib 0x000000018fd7d25c _pthread_start + 48
11 libsystem_pthread.dylib 0x000000018fd80d08 thread_start + 4
Thread 5 name: com.twitter.crashlytics.ios.MachExceptionServer
Thread 5:
0 libsystem_kernel.dylib 0x000000018fceded0 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x000000018fced3a8 mach_msg + 72
2 The_Name_Of_MyApp 0x000000010288d08c CLSMachExceptionServer + 1180
3 libsystem_pthread.dylib 0x000000018fd7d2fc _pthread_body + 128
4 libsystem_pthread.dylib 0x000000018fd7d25c _pthread_start + 48
5 libsystem_pthread.dylib 0x000000018fd80d08 thread_start + 4
Thread 6:
0 libsystem_pthread.dylib 0x000000018fd80cfc start_wqthread + 0
Thread 7:
0 libsystem_pthread.dylib 0x000000018fd80cfc start_wqthread + 0
Thread 8:
0 libsystem_pthread.dylib 0x000000018fd80cfc start_wqthread + 0
Thread 9:
0 libsystem_pthread.dylib 0x000000018fd80cfc start_wqthread + 0
Thread 10 name: com.apple.NSURLConnectionLoader
Thread 10:
0 libsystem_kernel.dylib 0x000000018fceded0 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x000000018fced3a8 mach_msg + 72
2 CoreFoundation 0x00000001900f1fb0 __CFRunLoopServiceMachPort + 236
3 CoreFoundation 0x00000001900ece4c __CFRunLoopRun + 1396
4 CoreFoundation 0x00000001900ec5b8 CFRunLoopRunSpecific + 436
5 CFNetwork 0x000000019070ce18 -[__CoreSchedulingSetRunnable runForever] + 212
6 Foundation 0x0000000190c133b0 __NSThread__start__ + 1040
7 libsystem_pthread.dylib 0x000000018fd7d2fc _pthread_body + 128
8 libsystem_pthread.dylib 0x000000018fd7d25c _pthread_start + 48
9 libsystem_pthread.dylib 0x000000018fd80d08 thread_start + 4
Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x0000000000000000 x1: 0x0000000000000000 x2: 0x0000000282718580 x3: 0x0000000000000000
x4: 0x0000000104870680 x5: 0x0000000000000000 x6: 0x0000000000000072 x7: 0x00000000000000a0
x8: 0x0000000103f03650 x9: 0x0000000000000000 x10: 0x000000000000001f x11: 0x0000000000000005
x12: 0x0000000000000005 x13: 0x0000000000000000 x14: 0x0000000000000068 x15: 0x00000001ae696425
x16: 0x000000018f34b858 x17: 0x0000000102601328 x18: 0x0000000000000000 x19: 0x0000000104853200
x20: 0x00000001048709c8 x21: 0x0000000280b73880 x22: 0x00000001c92684c0 x23: 0x0000000104870600
x24: 0x0000000281e51ec0 x25: 0x00000001c73e2000 x26: 0x0000000000000002 x27: 0x00000001c73e2000
x28: 0x0000000000000171 fp: 0x000000016d83c0b0 lr: 0x000000010268ca88
sp: 0x000000016d83bcc0 pc: 0x000000010268ca94 cpsr: 0x60000000
Here's a diagram outlining the relationship between the objects shown in the crash report. Basically at app launch the AppDelegate causes a LicenceManger object to be instantiated, which in turn causes a DatabaseManager and Database objects to be created, all of which are model type classes. Meanwhile the GUI is launching with InitialVC being a root VC which instantiates a TabBar VC which causes the instantiation of the SearchVC. The SearchVC accesses the DatabaseModel object and that is where the crash occurs.
And here is the code (reduced to just relevant portions, note the code is Swift except the DataBaseManager is Ojb-C)
InitialViewController
////////////////// InitialViewController ////////////////////////////
class InitialViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.perform(#selector(InitialViewController.start), with: nil, afterDelay: 1.5)
}
}
@objc func start() {
let tbvc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabBarViewControllerID") as! TabBarViewController
navigationController.pushViewController(tbvc, animated: true)
}
SearchViewController gets created as a consequence of there being a relationship segue between it and TabBarViewControllerSp
SearchViewController
///////////////////////// SearchViewController ///////////////////////////////
class SearchViewController: UITableViewController, UISearchBarDelegate {
var searchResultsList = DatabaseManager.instance().database.emptyList() /** line 67 **/
App Delegate
////////////////////// App Delegate ///////////////////////////
AppDelegate:didFinishLaunchingWithOptions() {
let _ = LicenseManager.instance
}
LicenseManager
//////////////////////// LicenseManager ////////////////////////
@objc class LicenseManager : NSObject {
@objc open static let instance = LicenseManager()
private let databaseManager = DatabaseManager.instance()
}
override private init() {
super.init()
}
DatabaseManager
///////////////////// DatabaseManager ////////////////////////
+ (DatabaseManager*) instance {
static DatabaseManager *theInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^ {
theInstance = [[DatabaseManager alloc] init];
});
return theInstance;
}
@interface DatabaseManager()
@property (strong, nonatomic) Database* _Nonnull database;
@property (strong, nonatomic) NSMutableDictionary* cityAndStateDictionary;
@end
@implementation DatabaseManager
- (id) init {
self = [super init];
if (self)
{
_database = Database.instance;
[_database openOrCreateDatabase];
dispatch_async(robocallerQueue(), ^{
[self readCityAndStateData];
});
}
return self;
}
//Populates a very large dictionary > 100K entries
- (void) readCityAndStateData
{
NSBundle* bundle = [NSBundle bundleForClass:[DatabaseManager class]];
NSString *filePath = [bundle pathForResource:@"CityState" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
Assert(data, @"unable to read CityState.json file");
NSError* __autoreleasing nserror;
NSDictionary* jsonParser = [NSJSONSerialization JSONObjectWithData: data
options: NSJSONReadingAllowFragments
error: &nserror];
if (nserror == nil)
{
self.cityAndStateDictionary = [[NSMutableDictionary alloc] init];
self.stateDictionary = [[NSMutableDictionary alloc] init];
for (NSDictionary *item in jsonParser)
{
NSNumber* num1 = item[@"Code1"];
NSNumber* num2 = item[@"Code2"];
NSString* key = [NSString stringWithFormat:@"%@%@", num1.stringValue, num2.stringValue];
NSString* city = item[@"City"];
NSString* state = item[@"State"];
NSString* value = [NSString stringWithFormat:@"%@, %@", [city capitalizedString], state];
(self.cityAndStateDictionary)[key] = value;
NSString* stateKey = [num1 stringValue];
(self.stateDictionary)[stateKey] = state;
}
self.cityAndStateDataLoaded = TRUE;
}
else
{
Assert(data, @"unable to parse CityState.json file");
}
}
Database
////////////////////// Database //////////////////////
@objcMembers class Database : NSObject {
open static let instance = Database()
fileprivate var configuration:Realm.Configuration? = nil
override init()
{
}
}
@objc func openOrCreateDatabase() {
configuration = Realm.Configuration(encryptionKey: Database.getKey() as Data)
}
class func getKey() -> NSData {
let string = "AED16D8B-7762-4CBF-A313-48FDCAD51B9C23456754635498123450ka&9dB6t"
let data = string.data(using: String.Encoding.utf8)
return data! as NSData
}
func emptyList() -> Results<Caller> {
let realm = try! Realm(configuration: configuration!)
let mdn = "DoesNotExist"
let searchTerm = "number == " + "\"" + mdn + "\""
let results = realm.objects(Caller.self).filter(searchTerm)
return results
}
Caller
//////////////// Caller ///////////
@objc public class Caller : Object {
@objc dynamic var name:String? = nil
// More simple types, strings, dates, ints etc.
}
EXC_BAD_ACCESS is an exception raised as a result of accessing bad memory. We're constantly working with pointers to memory in Swift that link to a specific memory address. An application will crash whenever we try to access a pointer that is invalid or no longer exists.
EXC_BAD_ACCESS (SIGSEGV) KERN_INVALID_ADDRESS means that the virtual address you're refererencing is not in the page tables or you don't have access. It's a virtual address that you're not allowed to access.
Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000. This indicates that your app crash because it tried to referenced NULL. Code Block. 0 CoreFoundation …
Replies. This EXC_BREAKPOINT crash is something that Swift uses when it wants to crash your app deliberately. The last method name is clearly a mangled name, but it's a pretty good guess that it's a result of your app calling 'fatalError' to crash itself.
This is not the result of force-unwrapping, which I guess is done intentionally to crash on purpose if the database can't be created. EXC_BAD_ACCESS KERN_INVALID_ADDRESS
occurs when you have a zombie: the code is trying to access deallocated memory (Similar crash messages here and here).
The following are general suggestions to eliminate zombies:
The culprit is amongst these: DatabaseManager.instance().database.emptyList()
DatabaseManager.instance()
This is created first in the AppDelegate via let _ = LicenseManager.instance
. Since the app crashes when calling SearchViewController.init(coder:)
, and not in the AppDelegate, it would be fair to assume that creating DatabaseManager.instance()
, Database.instance
in the AppDelegate is harmless.
DatabaseManager.instance().database
This is not the culprit either, as previously established: this is being created in the AppDelegate.
emptyList()
Which leaves us with this method. It is called in the main thread. As a method itself, the only case in which it would crash the app with a KERN_INVALID_ADDRESS
message, is if it is sent to a zombie. Which means that DatabaseManager.instance().database
doesn't exist in the main thread, yet. and this means that the 1.5
second delay in the InitialViewController
wasn't enough for the robocallerQueue
to return a non-nil DatabaseManager.instance().database
. From the crash report you can see that when the main thread (thread 0) crashes, thread 2 is still executing readCityAndStateData
.
I would suggest marking searchResultsList
as lazy, or using a completion handler instead of a 1.5 second delay.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With