如何调试仅在iPhone应用程序的发布目标上发生的EXC_BAD_ACCESS?

时间:2010-03-25 21:19:17

标签: iphone gdb nszombie

我正在开发一个iPhone应用程序。我有EXC_BAD_ACCESS只发生在发布目标中;当我构建调试目标时,不会发生异常。但是,当我将NSZombieEnabled环境变量设置为YES时,我仍然会得到EXC_BAD_ACCESS而没有更多信息。在执行发布目标时,NSZombieEnabled甚至可以工作吗?我不明白为什么不,因为gdb在两种情况下都在运行......

更新:这是堆栈顶部的打印输出:

#0  0x33369ebc in objc_msgSend ()
#1  0x3144f968 in -[EAInputStream _streamEventTrigger] ()
#2  0x3144fe78 in __streamEventTrigger ()
#3  0x338ae3a6 in CFRunLoopRunSpecific ()
#4  0x338adc1e in CFRunLoopRunInMode ()
#5  0x32ed6966 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#6  0x00005b06 in -[IOStreamDelegate removeMsg:] (self=0x142cc0, _cmd=<value temporarily unavailable, due to optimizations>, message=0x2fffe544) at /Users/robertmoretti/Documents/XXXXXXX/IOStreamDelegate.m:191

这是来自顶部objc_msgSend调用内部的gdb会话:

(gdb) p/x $r0
$6 = 0x3100000
(gdb) x/s $r1
0x32d7cff8:  "release"
(gdb) disassemble $pc
Dump of assembler code for function objc_msgSend:
0x33369ea8 <objc_msgSend+0>:    teq r0, #0  ; 0x0
0x33369eac <objc_msgSend+4>:    moveq   r1, #0  ; 0x0
0x33369eb0 <objc_msgSend+8>:    bxeq    lr
0x33369eb4 <objc_msgSend+12>:   push    {r3, r4, r5, r6}
0x33369eb8 <objc_msgSend+16>:   ldr r4, [r0]
0x33369ebc <objc_msgSend+20>:   ldr r5, [r4, #8]
0x33369ec0 <objc_msgSend+24>:   ldr r6, [r5]
0x33369ec4 <objc_msgSend+28>:   add r3, r5, #8  ; 0x8
0x33369ec8 <objc_msgSend+32>:   and r5, r6, r1, lsr #2
0x33369ecc <objc_msgSend+36>:   ldr r4, [r3, r5, lsl #2]
0x33369ed0 <objc_msgSend+40>:   teq r4, #0  ; 0x0
0x33369ed4 <objc_msgSend+44>:   add r5, r5, #1  ; 0x1
0x33369ed8 <objc_msgSend+48>:   beq 0x33369efc <objc_msgSend+84>
0x33369edc <objc_msgSend+52>:   ldr r12, [r4]
0x33369ee0 <objc_msgSend+56>:   teq r1, r12
0x33369ee4 <objc_msgSend+60>:   and r5, r5, r6
0x33369ee8 <objc_msgSend+64>:   bne 0x33369ecc <objc_msgSend+36>
0x33369eec <objc_msgSend+68>:   ldr r12, [r4, #8]
0x33369ef0 <objc_msgSend+72>:   teq r4, r4
0x33369ef4 <objc_msgSend+76>:   pop {r3, r4, r5, r6}
0x33369ef8 <objc_msgSend+80>:   bx  r12
0x33369efc <objc_msgSend+84>:   pop {r3, r4, r5, r6}
0x33369f00 <objc_msgSend+88>:   b   0x33369f04 <objc_msgSend_uncached>
End of assembler dump.
(gdb) p/x *$r0
$9 = 0x0

0x33369ebc <objc_msgSend+20>: ldr r5, [r4, #8]上发生异常。 r4刚刚给出r0指向的值,恰好为0.我想知道0x3100000的内存区域应该是什么。这是该区域的内存转储:

(gdb) x/256w 0x3100000
0x3100000:  0x00000000  0x0000a293  0xaa650505  0x00000000
0x3100010:  0x0000a294  0xaa670505  0x00000000  0x0000a295
0x3100020:  0xaa690505  0x00000000  0x0000a296  0xaa6b0505
0x3100030:  0x00000000  0x0000a297  0xaa6d0505  0x00000000
0x3100040:  0x0000a298  0xaa6f0505  0x00000000  0x0000a299
0x3100050:  0xaa710505  0x00000000  0x0000a29a  0xaa730505
0x3100060:  0x00000000  0x0000a29b  0xaa750505  0x00000000
0x3100070:  0x0000a29c  0xaa770505  0x00000000  0x0000a29d
0x3100080:  0xaa790505  0x00000000  0x0000a29e  0xaa7b0505
0x3100090:  0x00000000  0x0000a29f  0xaa7d0505  0x00000000
0x31000a0:  0x0000a2a0  0xaa7f0505  0x00000000  0x0000a2a1
0x31000b0:  0xaa810505  0x00000000  0x0000a2a2  0xaa830505
0x31000c0:  0x00000000  0x0000a2a3  0xaa850505  0x00000000
0x31000d0:  0x0000a2a4  0xaa870505  0x00000000  0x0000a2a5
0x31000e0:  0xaa890505  0x00000000  0x0000a2a6  0xaa8b0505
0x31000f0:  0x00000000  0x0000a2a7  0xaa8d0505  0x00000000
0x3100100:  0x0000a2a8  0xaa8f0505  0x00000000  0x0000a2a9
0x3100110:  0xaa910505  0x00000000  0x0000a2aa  0xaa930505
0x3100120:  0x00000000  0x0000a2ab  0xaa950505  0x00000000
0x3100130:  0x0000a2ac  0xaa970505  0x00000000  0x0000a2ad
0x3100140:  0xaa990505  0x00000000  0x0000a2ae  0xaa9b0505
0x3100150:  0x00000000  0x0000a2af  0xaa9d0505  0x00000000
0x3100160:  0x0000a2b0  0xaa9f0505  0x00000000  0x0000a2b1
0x3100170:  0xaaa10505  0x00000000  0x0000a2b2  0xaaa30505
0x3100180:  0x00000000  0x0000a2b3  0xaaa50505  0x00000000
0x3100190:  0x0000a2b4  0xaaa70505  0x00000000  0x0000a2b5
0x31001a0:  0xaaa90505  0x00000000  0x0000a2b6  0xaaab0505
0x31001b0:  0x00000000  0x0000a2b7  0xaaad0505  0x00000000
0x31001c0:  0x0000a2b8  0xaaaf0505  0x00000000  0x0000a2b9
0x31001d0:  0xaab10505  0x00000000  0x0000a2ba  0xaab30505
0x31001e0:  0x00000000  0x0000a2bb  0xaab50505  0x00000000
0x31001f0:  0x0000a2bc  0xaab70505  0x00000000  0x0000a2bd
0x3100200:  0xaab90505  0x00000000  0x0000a2be  0xaabb0505
0x3100210:  0x00000000  0x0000a2bf  0xaabd0505  0x00000000
0x3100220:  0x0000a2c0  0xaabf0505  0x00000000  0x0000a2c1
0x3100230:  0xaac10505  0x00000000  0x0000a2c2  0xaac30505
0x3100240:  0x00000000  0x0000a2c3  0xaac50505  0x00000000
0x3100250:  0x0000a2c4  0xaac70505  0x00000000  0x0000a2c5
0x3100260:  0xaac90505  0x00000000  0x0000a2c6  0xaacb0505
0x3100270:  0x00000000  0x0000a2c7  0xaacd0505  0x00000000
0x3100280:  0x0000a2c8  0xaacf0505  0x00000000  0x0000a2c9
0x3100290:  0xaad10505  0x00000000  0x0000a2ca  0xaad30505
0x31002a0:  0x00000000  0x0000a2cb  0xaad50505  0x00000000
0x31002b0:  0x0000a2cc  0xaad70505  0x00000000  0x0000a2cd
0x31002c0:  0xaad90505  0x00000000  0x0000a2ce  0xaadb0505
0x31002d0:  0x00000000  0x0000a2cf  0xaadd0505  0x00000000
0x31002e0:  0x0000a2d0  0xaadf0505  0x00000000  0x0000a2d1
0x31002f0:  0xaae10505  0x00000000  0x0000a2d2  0xaae30505
0x3100300:  0x00000000  0x0000a2d3  0xaae50505  0x00000000
0x3100310:  0x0000a2d4  0xaae70505  0x00000000  0x0000a2d5
0x3100320:  0xaae90505  0x00000000  0x0000a2d6  0xaaeb0505
0x3100330:  0x00000000  0x0000a2d7  0xaaed0505  0x00000000
0x3100340:  0x0000a2d8  0xaaef0505  0x00000000  0x0000a2d9
0x3100350:  0xaaf10505  0x00000000  0x0000a2da  0xaaf30505
0x3100360:  0x00000000  0x0000a2db  0xaaf50505  0x00000000
0x3100370:  0x0000a2dc  0xaaf70505  0x00000000  0x0000a2dd
0x3100380:  0xaaf90505  0x00000000  0x0000a2de  0xaafb0505
0x3100390:  0x00000000  0x0000a2df  0xaafd0505  0x00000000
0x31003a0:  0x0000a2e0  0xab050505  0x00000000  0x0000a2e1
0x31003b0:  0xab070505  0x00000000  0x0000a2e2  0xab090505
0x31003c0:  0x00000000  0x0000a2e3  0xab0b0505  0x00000000
0x31003d0:  0x0000a2e4  0xab0d0505  0x00000000  0x0000a2e5
0x31003e0:  0xab0f0505  0x00000000  0x0000a2e6  0xab110505
0x31003f0:  0x00000000  0x0000a2e7  0xab130505  0x00000000

我真的不知道还有什么可以尝试;希望有更多iphone经验的人能够将这种记忆视为有意义的事物。

更新2:我刚刚发现只有在使用-O2,-O3和-Os进行编译时才会出现此问题。不确定这意味着什么。

3 个答案:

答案 0 :(得分:4)

objc_msgSend中,r0包含指向消息接收者的指针。当您的应用尝试加载接收器指向的内容时,它会崩溃。最可能的解释是,您要么发送一个尚未初始化的对象,要么发布一个已经被释放的对象,但还有其他可能性。

您也可以查看“So you crashed in objc_msgSend”;它是关于英特尔OS X平台的,但其中大部分也适用于iPhone OS。

答案 1 :(得分:3)

当您启用NSZombieEnabled时,您应该检查控制台,因为它可能会告诉您哪条线路正在获得EXC_BAD_ACCESS。从那里你可以解决它。不要忘记将其禁用以进行最终发布。

答案 2 :(得分:2)

基于你的gdb会话,你似乎有可能过度释放一些对象,虽然我同意0x3100000似乎不太可能。您是否尝试过运行Build and Analyze?静态分析可以捕获许多常见的过度发布错误。

基于该内存地址,缓冲区溢出似乎更有可能。这也可以解释为什么当你使用-O2或更高版本进行编译时,它只会在发布模式下崩溃。优化可能会以这样一种方式布置内存:缓冲区溢出会导致发布模式崩溃但不会导致调试模式崩溃。

你在做旧学校C void *指针时做什么时髦吗?使用任何空终止的C字符串?做任何指针运算?