我有一个像这样的 SIGSEGV/SEGV_ACCERR 崩溃:
Thread 0 Crashed:
0 libobjc.A.dylib 0x39c69f2a _objc_release + 10
1 CoreFoundation 0x31cf4441 __CFAutoreleasePoolPop + 17
2 Foundation 0x326c8185 __NSThreadPerformPerform + 605
3 CoreFoundation 0x31d86683 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
4 CoreFoundation 0x31d85ee9 __CFRunLoopDoSources0 + 213
5 CoreFoundation 0x31d84cb7 __CFRunLoopRun + 647
6 CoreFoundation 0x31cf7ebd _CFRunLoopRunSpecific + 357
7 CoreFoundation 0x31cf7d49 _CFRunLoopRunInMode + 105
8 GraphicsServices 0x358c32eb _GSEventRunModal + 75
9 UIKit 0x33c0d301 _UIApplicationMain + 1121
10 MyApp 0x0007471b main (main.m:15)
问题是 SEGV_ACCERR 地址总是无效的。我见过以下地址:0xa2142302
, 0x51e9d281
, 0x11e1af4e
, 0x10
, 例如。我的理解是,里面的 SEGV_ACCERR 地址_objc_release()
应该是指向被释放对象或其类对象的指针。如您所见,上述示例地址的前三个未对齐(假设malloc()
只返回 16 字节对齐的地址),最后一个显然是伪造的。
崩溃发生在__CFAutoreleasePoolPop()
,这表明虚假指针以某种方式被自动释放池收集。我的理解是,自动释放池收集指针的唯一方法是成为接收-autorelease
消息的有效 Obj-C 对象。
如果我的两个前提都是正确的,那么我的内存损坏情况很糟糕。换句话说,接收到的有效 Obj-C 对象-autorelease
进入自动释放池,它的内存位置被垃圾覆盖,当自动释放池试图释放它时,它取消引用了一个无效指针。
什么样的错误会像这样破坏内存?我可以想到memcpy()
类似函数、堆栈溢出、缓冲区溢出。我还能寻找什么?
下面是一个典型的线程状态示例。SEGV_ACCERR 地址总是 r1
+ 16,r10
总是和= + 48,但我只能这么说。 0xa3a3a3a3
r6
r4
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x51e9d281
...
Thread 0 crashed with ARM Thread State:
r0: 0x1e865730 r1: 0x51e9d271 r2: 0x00000002 r3: 0xc4d443fb
r4: 0x1e0ff000 r5: 0x3bc64bd0 r6: 0x1e0ff030 r7: 0x2fdbdddc
r8: 0x1e0ff030 r9: 0x0015991c r10: 0xa3a3a3a3 r11: 0x00000088
ip: 0x3bc5f800 sp: 0x2fdbddbc lr: 0x39c69489 pc: 0x39c69f2a
cpsr: 0x20000030
不幸的是,我自己无法重现崩溃,所有报告均来自实际用户。任何想法都非常感谢。