Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to determine possible causes of EXC_BAD_ACCESS (which occurs during app startup)

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.

enter image description here

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.
}
like image 933
Gruntcakes Avatar asked Sep 27 '18 21:09

Gruntcakes


People also ask

What causes Exc_bad_access?

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.

What does Kern_invalid_address mean?

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.

What is Exc_bad_access Kern_invalid_address?

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 …

What is Exc_breakpoint?

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.


1 Answers

Zombies

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:

  • Enable Zombie Objects in Xcode in the Diagnostics tab in your scheme
  • Look for zombies in your project using Instruments

Line 67

The culprit is amongst these: DatabaseManager.instance().database.emptyList()

  1. 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.

  2. DatabaseManager.instance().database

    This is not the culprit either, as previously established: this is being created in the AppDelegate.

  3. 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.


Solutions

I would suggest marking searchResultsList as lazy, or using a completion handler instead of a 1.5 second delay.

like image 79
ielyamani Avatar answered Sep 30 '22 19:09

ielyamani