IMP methodForSelector EXC_BAD_ACCESS 崩溃
Posted
技术标签:
【中文标题】IMP methodForSelector EXC_BAD_ACCESS 崩溃【英文标题】:IMP methodForSelector EXC_BAD_ACCESS crash 【发布时间】:2015-02-03 19:10:09 【问题描述】:我收到了几份崩溃报告,唯一的共同点是它们都是 iPhone 5。我无法在 iPhone 5s 或 6 上重现崩溃,所以我认为它是 64/32位问题。不过,该代码在运行 ios 7 的 iPhone 4s 上也能正常运行。
崩溃发生在此处的最后一行:
IMP imp = [self.delegate methodForSelector:aSelector];
id (*func)(id, SEL, id) = (void *)imp;
func(self.delegate, aSelector, self);
老实说,我不明白这 3 行代码。我发现他们在使用[self.delegate performSelector:aSelector withObject:self];
时克服了编译器警告may cause a leak because its selector is unknown
当我使用 performSelector
推送更新时,它不会崩溃。
我需要将self
的参数与选择器一起传递,这就是我使用IMP
并添加self
作为第三个参数的原因,这是我应该如何阅读它的原因。
实际的崩溃日志并没有透露太多:
Crashed: com.apple.main-thread EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x00000100 Thread : Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x30ca26b8 objc_retain + 7
1 Timeout 0x0009e2a1 __50-[BaseOperation finishedSuccessfullyWithSelector:]_block_invoke_2 (BaseOperation.m:47)
2 libdispatch.dylib 0x311e87bb
_dispatch_call_block_and_release + 10
3 libdispatch.dylib 0x311efe8b _dispatch_after_timer_callback + 66
4 libdispatch.dylib 0x311e87a7 _dispatch_client_callout + 22
5 libdispatch.dylib 0x311f9253 _dispatch_source_latch_and_call + 626
6 libdispatch.dylib 0x311ea2ed _dispatch_source_invoke + 212
7 libdispatch.dylib 0x311ebe1f _dispatch_main_queue_callback_4CF + 330
8 CoreFoundation 0x234a39d1 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
9 CoreFoundation 0x234a20d1 __CFRunLoopRun + 1512
10 CoreFoundation 0x233f0211 CFRunLoopRunSpecific + 476
11 CoreFoundation 0x233f0023 CFRunLoopRunInMode + 106
12 GraphicsServices 0x2a7e90a9 GSEventRunModal + 136
13 UIKit 0x269fc1d1 UIApplicationMain + 1440
14 Timeout 0x000a265b main (main.m:14)
有没有人可以解释一下?
谢谢
编辑---- 我现在也看到 iPad 3 (iOS 8.1.2) 和 iPhone 5 (iOS 8.1) 上的崩溃。但是我自己还是无法重现,我还尝试了 iPod (iOS 8.1) 和 iPad mini Retina (iOS 8.1.3)。这真的让我很烦(双关语)。
编辑 2 ----
我添加了一些 Crashlytics 日志来记录 self.delegate
self
imp
和 func
,它们看起来都很好!那么为什么下一行会崩溃呢?
0 | 00:01:33:665 | $ __50-[BaseOperation finishedSuccessfullyWithSelector:]_block_invoke_2 : connectComplete:
1 | 00:01:33:665 | $ delegate: <BaseMenuViewController: 0x17e5e780>
2 | 00:01:33:666 | $ self: <ConnectOperation_Virgin: 0x1902a490>name = '(null)'
3 | 00:01:33:667 | $ imp: 0xaa345
4 | 00:01:33:667 | $ func: 0xaa345
【问题讨论】:
【参考方案1】:我遇到了同样的问题,6 个月前的工作代码现在崩溃了,通过这些更改修复了它:
//旧代码
IMP imp = [_target methodForSelector:_action];
id (*func)(id, SEL, id) = (void *)imp;
func(_target, _action, params);
//替换为
void (*imp)(id, SEL, id) = (void(*)(id,SEL,id))[_target methodForSelector:_action];
if( imp ) imp(_target, _action, params);
【讨论】:
以上是关于IMP methodForSelector EXC_BAD_ACCESS 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
错误:“线程 1:EXC_BAD_ACCESS(代码=EXC_I386_GPFLT)
线程 1:EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP,subcode=0*0) 错误
线程 1:EXC_BAD_ACCESS(代码=EXC_I386_GPFLT)
错误“线程 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)”是啥意思?
错误 - 线程 1 exc_bad_instruction(代码=exc_1386_invop 子代码=0x0)
斯威夫特 3 - 'EXC_BAD_INSTRUCTION(代码 = EXC_1386_INVOP,子代码 = 0x0)' 错误