40

I have this stack trace in Fabric:

enter image description here

My question: From the crash log, is the function 'formatMessageAuthorName' the only cause for this EXC_BREAKPOINT crash? E.g., are there other possible causes for the crash apart from the code inside this function?

Here is my formatMessageAuthorName function:

private static func formatMessageAuthorName(firstname: String, lastname: String?=nil) -> String {
    // Capitalise first character of firstname
    var Cap_firstname = firstname
    Cap_firstname.replaceRange(Cap_firstname.startIndex...Cap_firstname.startIndex, with: String(Cap_firstname[Cap_firstname.startIndex]).capitalizedString)


    guard let lastname = lastname else { return Cap_firstname }

    // if has lastname & first char, capitalise too and concat with firstname.
    if let firstCharLastName = lastname.characters.first {
        return "\(Cap_firstname) \(String(firstCharLastName).uppercaseString)."
    } else {
        return firstname
    }
}

My assumption

The only clue that I know that will make the function crash is when 'firstname' is an empty string, it will crash here since it accesses invalid array index:

String(Cap_firstname[Cap_firstname.startIndex])

However, I'm still skeptical about this assumption, since I'm quite sure that 'firstname' is not empty (it's retrieved from server). I even tested it by logging into some user accounts that has this crash, and using that page (MessageViewController), but I never had the crash myself and firstname is shown correctly. It also seems to not be about iOS versions as I received crash from iOS 8, 9, and 10.

I have this crash a lot (>300) after my recent app update and I have no idea why as it never happens before, the code here does not change through the update, and I can never reproduce it with the effected users.

If the culprit can only be the code in this function, and no other possibilities (like multi-threading, Realm etc.), I can turn to focus on the server issues instead, like how 'firstname' might be an empty string. But still, I can't imagine how it could happen, since I already used those user accounts and never have this crash myself.

Thanks a lot.

aunnnn
  • 1,882
  • 2
  • 17
  • 23

1 Answers1

33

EXC_BREAKPOINT is always triggered by executing a trap instruction of some sort(*) and the exception gets delivered directly to the thread that executed the trap instruction. So if you are seeing a crash report that says this thread with this stack got an EXC_BREAKPOINT, that means that thread really did do something that executed a trap instruction.

You could probably see this by looking at the crash address in your binary, you will see some kind of trap instruction there. The swift standard library uses trap instructions to signal various kinds of invalid access errors, and that code probably got inlined into the function that's crashing. So this makes sense of your example above.

(*) EXC_BREAKPOINT can also be used for data watches, but that's not what's happening here, and anyway they would still be delivered to the thread that accessed the watched data...

mokagio
  • 16,391
  • 3
  • 51
  • 58
Jim Ingham
  • 25,260
  • 2
  • 55
  • 63
  • @Jim Ingham is there a way to find what function in the swift standard library is actually trapping and causing that crash? – Valerio Santinelli Jun 26 '19 at 08:20
  • 2
    Using a "trap" for error handling is nice because it stops the process with the zeroth frame at the point of the error. So in most cases, the bottom most frame on the stack is the culprit. If you don't have symbols for the bottom-most frame, you could try looking up the stack to the first public entry point into the library, since the bottom-most frame is likely just a utility function helping that call. If this is happening in a frame in your code, the swift library call has likely been inlined into your code. I don't think there's a good way to track swift inlining at present. – Jim Ingham Jun 26 '19 at 17:46