I have a growing collection of iOS crash reports (3 to 4 per day) which crash inside calloc or malloc, saying "EXC_BAD_ACCESS KERN_INVALID_ADDRESS" and then listing a pointer address which either looks like a tagged pointer, like
0x0000000000000026, 0x000000000000001c, 0x000000000000005a
or pointers that look suspiciously low, like
0x0000000000000010, 0x0000000000000020, 0x0000000000000030.
Stats say it's happening for 5% of users, we've only been able to trigger it in the office once, and the debugger wasn't attached. So I haven't been able to trap it with zombies, or address sanitizer.
So my questions are:
1) Are the 0x10, 0x20, 0x30 also tagged pointers? or just really low value real pointers, and thus likely a different problem?
2) What could cause tagged pointers to actually get free'd so that they'd ever end up available for malloc or calloc? We do use both Obj-c and swift, but I thought the compiler would handle conversions between obj-c tagged objects like NSNumber's and NSDate's and swift types. Could a lack of @objc on an extension's override of a protocol method cause the conversion to not happen? Should I be looking into code that accidently calls CFRelease on an NSNumber or NSDate? I don't have any -f-no-arc files in the project, but I do have a few pre-compiled 3rd party libraries in the app.
2b) Which other NSObject subclasses can be tagged pointers?
3) How do I discover where the instance was allocated, or where it was free'd without either releasing the modified app to production and without having it hooked up to the debugger? I can have our qa person tap the app incessantly, but it would work better if we had a way to capture the addresss sanitizer or zombie output and send it up via fabric crash reports? Can I catch the contents that zombies or address sanitizer would normally print to the console and include it in the crash report? I have a synchronous way to add arbitrary lines of text to the crash report if I can intercept it before crashlytics gets it, but my experience with that is limited to intercepting NSExceptions, and this is way deeper than NSException.
3b) Is there maybe a way to get it to crash when the bad value is free'd instead or reused so our internal qa builds can at least narrow down the scope of what got released wrong, instead of "literally maybe anything"?