我在下面的回溯中会遇到很多崩溃,我找不到原因。
根据Apple -NSObject(NSObject) doesNotRecognizeSelector:当一个新对象被分配到先前被释放的对象占用的内存中时,就会发生。
备注:以前被释放的对象消息传递可能会引发NSInvalidArgumentException,而不是以内存访问冲突导致程序崩溃。当一个新对象被分配到先前被释放的对象占用的内存中时,就会发生这种情况。如果您的应用程序由于未登录的NSInvalidArgumentException而崩溃(查找-NSObject(NSObject) doesNotRecognizeSelector:在异常回退跟踪中),请考虑使用僵尸工具对应用程序进行分析,以消除内存管理不当是原因的可能性。
https://developer.apple.com/library/archive/technotes/tn2151/_index.html
但是回溯的其余部分是怎么回事,特别是-UIUndoGestureInteraction didMoveToView:这件事?
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0
Last Exception Backtrace:
0 CoreFoundation 0x1ae45498c __exceptionPreprocess + 220 (NSException.m:199)
1 libobjc.A.dylib 0x1ae17d0a4 objc_exception_throw + 56 (objc-exception.mm:565)
2 CoreFoundation 0x1ae35843c -[NSObject(NSObject) doesNotRecognizeSelector:] + 140 (NSObject.m:144)
3 UIKitCore 0x1b24902a8 -[UIResponder doesNotRecognizeSelector:] + 296 (UIResponder.m:659)
4 CoreFoundation 0x1ae458e08 ___forwarding___ + 1324 (NSForwarding.m:3325)
5 CoreFoundation 0x1ae45abec _CF_forwarding_prep_0 + 92
6 UIKitCore 0x1b2353040 -[UIUndoGestureInteraction didMoveToView:] + 108 (UIUndoGestureInteraction.m:725)
7 UIKitCore 0x1b28eb3c4 _setInteractionView + 84 (UIView.m:16421)
8 UIKitCore 0x1b28eb2a0 -[UIView(Dragging) addInteraction:] + 268 (UIView.m:16450)
9 UIKitCore 0x1b26cd2b8 -[UIEditingOverlayViewController _addInteractions] + 260 (UIEditingOverlayViewController.m:79)
10 UIKitCore 0x1b1e5b2ec -[UIViewController _setViewAppearState:isAnimating:] + 832 (UIViewController.m:4695)
11 UIKitCore 0x1b1e5b6fc __52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke + 268 (UIViewController.m:4758)
12 CoreFoundation 0x1ae42773c __NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__ + 16 (NSArrayHelpers.m:9)
13 CoreFoundation 0x1ae32b86c -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 152 (NSArrayI.m:108)
14 UIKitCore 0x1b1e5b49c -[UIViewController _setViewAppearState:isAnimating:] + 1264 (UIViewController.m:4736)
15 UIKitCore 0x1b1e5d530 __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke + 44 (UIViewController.m:5272)
16 UIKitCore 0x1b1e5c32c -[UIViewController _executeAfterAppearanceBlock] + 88 (UIViewController.m:5050)
17 UIKitCore 0x1b246bca4 _runAfterCACommitDeferredBlocks + 584 (UIApplication.m:3027)
18 UIKitCore 0x1b245b7c0 _cleanUpAfterCAFlushAndRunDeferredBlocks + 232 (UIApplication.m:2986)
19 UIKitCore 0x1b248b594 _afterCACommitHandler + 76 (UIApplication.m:3048)
20 CoreFoundation 0x1ae3d1c48 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32 (CFRunLoop.c:1758)
21 CoreFoundation 0x1ae3ccb34 __CFRunLoopDoObservers + 416 (CFRunLoop.c:1868)
22 CoreFoundation 0x1ae3cd100 __CFRunLoopRun + 1308 (CFRunLoop.c:2910)
23 CoreFoundation 0x1ae3cc8bc CFRunLoopRunSpecific + 464 (CFRunLoop.c:3192)
24 GraphicsServices 0x1b8238328 GSEventRunModal + 104 (GSEvent.c:2246)
25 UIKitCore 0x1b24626d4 UIApplicationMain + 1936 (UIApplication.m:4753)
26 JustConnect 0x10425ca60 main + 68 (APIInfoUser.swift:7)
27 libdyld.dylib 0x1ae257460 start + 4发布于 2019-10-28 08:17:32
以下是来自苹果开发人员和技术支持的回应:
这里要注意的关键是,从0到5帧的回溯只是与未识别的选择器相关联的样板。也就是说,frame 6在对象上调用了一个方法,对象没有识别该选择器,因此它进入了object运行时转发基础结构(框架5到4)。这在UIResponder (frame 3)中出现,因为UIResponder支持某种类型的通用消息转发。消息转发失败,因此UIResponder调用Super(Frame 2),然后抛出异常。
因此,真正的问题是,框架6中发生了什么。要了解更多这方面的内容,可以反汇编代码(-:
(lldb) disas -n '-UIUndoGestureInteraction didMoveToView:‘UIUndoGestureInteraction: 0x1bbe92fd4 <+0>:stp x22,x21,sp,#-0x30!0x1b2fd8 <+4>:stp x20,#0x10 0x1bbe92fdc <+8>:stp x29,x30,sp,#0x20 0x1bbe92fe0 <+12>:加x29,#0x20;=0x20 0x1bbe92fe4 <+16>:mov x21,x2 0x1bbe92fe8 <+20>:mov x19,x0 0x1bbe92fec <+24>:add x20,x0,#0x10;=0x10 0x1bbe92ff0 <+28>:mov x0,x20 0x1bbe92ff4 <+32>:mov x1,x2 0x1bbe92ff8 <+36>:bl 0x1b7cd7d8;objc_storeWeak 0x1bbe92ffc <+40>:cbz,0x1bbe930a8;<+212> 0x1bbe93000 <+44>:add x8,208464 0x1bbe93004 <+48>:add x1,x8,#0x7b1;=0x7b1 0x1bbe93008 <+52>:mov x0,x19 0x1bbe9300c <+56>:bl 0x1b7cb9180;objc_msgSend 0x1bbe93010 <+60>:mov x0,x20 0x1bbe93014 <+64>:bl 0x1b7cd7a80;objc_loadWeakRetained 0x1bbe93018 <+68>:mov x20,x0 0x1bbe9301c <+72>:adrp x8,208304 0x1bbe93020 <+76>:add x1,x8,#0xc 04;=0xc04 0x1bbe93024 <+80>:bl 0x1b7cb9180;objc_msgSend 0x1bbe93028 <+84>:mov x29,x29 0x1bbe9302c <+88>:bl 0x1b7cd8864;objc_retainAutoreleasedReturnValue 0x1bbe93030 <+92>:mov x21,x0 0x1bbe93034 <+96>:adrp x8,208502 0x1bbe93038 <+100>:add x1,x8,#0xbb7;=0xbb7 0x1bbe9303c <+104>:bl 0x1b7cb9180;objc_msgSend 0x1bbe93040 <+108>:stp d0、d1、x19、#0x100 --你可以在这里学到很多东西。首先,反向跟踪中的框架6的偏移量为+108,因此失败的实际调用位于+104。一个objc_msgSend,有两个标准参数,目标对象和选择器。在64位Arm上,这些映射分别映射到x0和x1 .
让我们先看看选择器。这是由+96和+100的两个指令构造的。这两个指令构成一个PC相对地址.adrp指令(‘add相对于页面’)接受当前PC (0x1bbe93034),清除底部12位(0x1bbe93000,记住历史页面大小为4096 1),然后取文字,将其左移12位(208502 << 12),然后将其添加进去。添加指令要简单得多。它接受前面计算的结果,并添加0xbb7 (注意从十进制切换到十六进制!)。
如果在调试器中运行此计算,您将看到以下内容:
(lldb) p (char *) ( 0x1bbe93000+(208502<<12)+0xbb7) (char *) $1 = 0x00000001eed09bb7 "actualSceneBounds“
所以选择器是actualSceneBounds。凉爽的。
现在让我们来看看这个对象。在调用(+104)时,预期这将出现在x0中。在+92,我们看到它将x0复制到x21,但这只是一个干扰。实际上,x0是objc_retainAutoreleasedReturnValue +88的函数结果。该函数接受并返回一个对象,因此x0是消息发送到+80时返回的值。与前面做的相同的相对页面技巧,我们看到调用的选择器是-window。但被召唤的对象是什么?
解决这个问题的方法是…well…因为objc_storeWeak / objc_loadWeakRetained舞有点复杂。我相信它归结为通过x2传递给这个方法的值,即第三个参数。基于方法名,这显然是一个视图(记住,对于Objective方法,前两个参数x0和x1持有目标和选择器,因此x2持有第一个实际参数)。
因此,总括而言:
这个方法似乎有一个视图,parameter.
我对UIKit的了解还不够,无法解释这方面的背景。我在这里有几个建议:
。
分享和享受
-
1在64位Arm上,实际页面大小通常为64 KiB,但是adrp指令使用历史页面大小4096,因为它匹配添加指令中的最大文本大小。
发布于 2022-11-24 20:20:20
我遇到了一个类似的问题,结果发现只有在代码被优化的版本构建中才会发生崩溃(我猜类初始化/声明在被引用之前被跳过了)
在没有对代码进行优化的调试构建中没有发生这种情况。
作为一种解决方案,我将构建设置> Swift编译器-代码生成>优化级别更新为无版本版本。
https://stackoverflow.com/questions/58408690
复制相似问题