Help with crash in objc_msgSend (no app code in stack trace)

Hello,

I am attempting to track down a crash that isn't giving me a lot of information (crash log included below). Here is what I know so far:

  • According to Apple documentation, a crash in objc_msgSend is due to a zombie object. So I have been trying to recreate the crash with zombies enabled, without success.
  • The address of the object being messaged is 0x0000000000000010, a suspect value. It's always 0x10, across thousands of crash reports with slightly differing stack traces and circumstances. That makes me wonder if the runtime is trying to tell me something with that address, but I have been unable to find any documentation to that effect.
  • We have internal analytics that suggest that the crash always happens after the user activates the system PIP video player, and usually also after backgrounding the app. It is also common (though not universal) that the crash occurs after the user has paused the video (and sometimes resumed it).

This post is a bit of a Hail Mary; I'm hoping that maybe someone on here will see something I missed, because I have exhausted most of my own avenues of investigation. Many thanks for any help you can provide.

Replies

According to Apple documentation, a crash in objc_msgSend is due to a zombie object.

That’s one common cause of such crashes, but it’s not the only one. Let’s look at your case…

The address of the object being messaged is 0x0000000000000010

That’s not the address of the object being messaged. Consider this:

(lldb) disas -n objc_msgSend
libobjc.A.dylib`objc_msgSend:
    0x189efc800 <+0>:   cmp    x0, #0x0
    0x189efc804 <+4>:   b.le   0x189efc8d0               ; <+208>
    0x189efc808 <+8>:   ldr    x14, [x0]
    0x189efc80c <+12>:  and    x16, x14, #0x7ffffffffffff8
    0x189efc810 <+16>:  mov    x10, x0
    0x189efc814 <+20>:  movk   x10, #0x6ae1, lsl #48
    0x189efc818 <+24>:  autda  x16, x10
    0x189efc81c <+28>:  mov    x15, x16
    0x189efc820 <+32>:  ldr    x11, [x16, #0x10]

and this snippet from your crash report [1]:

Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x000000014ea07ed0 …  x2: 0xffffffffffffffd0 …
    x4: 0x00000002806e8740 …  x6: 0x0000000000000013 …
    x8: 0xd98a7a153e4200fa … x10: 0x6ae100014ea07ed0 …
   x12: 0x00000000000007fb … x14: 0x0000000000000000 …
   x16: 0x0000000000000000 … x18: 0x0000000000000000 …

In your crash report, x16 is 0, aka nil, thus the instruction at +32 crashes referencing a field at offset 0x10. Hence the crashing address of 0x0000000000000010.

Now go back through the code looking at where x16 comes from. There’s some tricky stuff there, but ultimately it’s derived from x14 at +12 which, in turn, is found by loading the word at x0. x0 is 0x000000014ea07ed0. x0 is also the first argument to the objc_msgSend function, that is, the self parameter.

So, self is a reasonable-ish looking pointing, but the isa pointer at self is nil. Hence your crash.

As to how it got that way, it’s hard to say. Over-released objects, which is what Zombies is designed to detect, are a common cause of problems like this, but there are others. It’s possible that some with deep UIKit experience, which is not me!, may have more to say on this.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] I’m assuming that that this crash report can be trusted, which isn’t 100% guaranteed because there's a third-party crash reporter in the mix.

Thank you for that detailed reply. You're making me want to learn more about the low-level details of process execution. And ARM assembly while I'm at it. Add it to the list I guess.

What was it in the crash report that signaled that the invalid address was actually an offset and not a literal address? It never would have occurred to me that I would need to disassemble objc_msgSend in order to interpret the report.[1]

Given that the crash seems to be happening after the user enters PIP, and also the presence of code that appears to be updating auto layout constraints in response to the changing trait environment that a transition to PIP likely entails, I'd guess we have a constraint somewhere that is referencing a deallocated view. That is what I would call an informed wild guess, because I haven't been able to recreate the thing myself.

[1] Which can probably be trusted. I would love to get rid of Crashlytics and just use the Apple features, but as I'm sure you understand, that is not my decision to make.

What was it in the crash report that signaled that the invalid address was actually an offset and not a literal address?

The actual value. On Apple’s 64-bit systems the bottom 4 GiB is unmapped, so there are no valid addresses less than 0x0000_0001_0000_0000. And when you see an address that’s close to 0, aka nil, an offset is the most common cause.

I'd guess we have a constraint somewhere that is referencing a deallocated view.

Quite possibly. One of the downsides of having spent the last N years decades dealing with low-level stuff is that I don’t know much about UI frameworks |-:

Did you have any luck with Zombies? That’s always a good place to star with issues like this. See my Standard Memory Debugging Tools post for more info on that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"