1.前言
最近线上突然多了一些crash,类型是SEGV_ACCER,一看就认为是对象野指针了,基本都是多线程读写导致的;
但是仔细再一看crash堆栈,不是平常的objc_xxxx,而是 cache_getImp 这就有点怪了,和平常的objc_msgSend或objc_retain等挂的不太一样;
我们实际的业务代码挂在如下
[delegate performSelector:didReceiveDataSelector withObject:self withObject:data];
实际的crash堆栈是
Thread 0 Crashed:
0 libobjc.A.dylib 0x00000001837bcd04 _cache_getImp + 4
1 libobjc.A.dylib 0x00000001837b1900 _lookUpImpOrNil + 12
2 libobjc.A.dylib 0x00000001837a7578 class_respondsToSelector + 32
3 CoreFoundation 0x00000001845f41d8 ____forwarding___ + 372
4 CoreFoundation 0x00000001844da41c _CF_forwarding_prep_0 + 80
5 mttlite 0x0000000102cd94f4 -[QBASIHTTPRequest passOnReceivedData:] (QBASIHTTPRequest.m:2111)
6 Foundation 0x000000018503a0ec ___NSThreadPerformPerform + 340
7 CoreFoundation 0x0000000184597404 ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
+ 24
8 CoreFoundation 0x0000000184596c2c ___CFRunLoopDoSources0 + 276
2.分析
这个问题又是不好复现的问题,那只能沿着Crash堆栈反向去推了;
顺手就找来objc源码对比着看;
挂的代码在_cache_getImp 这里实际上是一段汇编代码(苹果为了优化效率该函数时直接汇编实现的),
oc对应源码