2010-03-25 2 views
14

Я разрабатываю приложение для iPhone. У меня есть EXC_BAD_ACCESS, который встречается только в цели релиза; когда я создаю цель отладки, исключение не возникает. Однако, когда я установил переменную окружения NSZombieEnabled в YES, я все еще получаю EXC_BAD_ACCESS без дополнительной информации. Возможно ли, что NSZombieEnabled будет работать при выполнении цели релиза? Я не понимаю, почему нет, так как GDB работает в обоих случаях ...Как отлаживать EXC_BAD_ACCESS, который встречается только для цели релиза для iPhone-приложения?

Update: здесь распечатку верхней части стека:

#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 

Вот GDB сессию внутри objc_msgSend вызова в верхней части:

(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

Когда вы разрешаете NSZombieEnabled, вы должны проверить консоль, поскольку она, вероятно, скажет, в какой строке вы получаете EXC_BAD_ACCESS. Оттуда вы сможете это исправить. Не забудьте отключить его для окончательной версии.

+0

Консоль ничего не говорит мне, к сожалению; просто он получил исключение. Тогда он просто прыгает на gdb –

+0

Спасибо за трюк: не решил проблему для меня, но по крайней мере с NSZombieEnabled У меня есть некоторая информация :) – Rick77

4

В objc_msgSend, r0 содержит указатель на приемник сообщения. Ваше приложение сбой, когда оно пытается загрузить то, на что указывает получатель. Наиболее вероятное объяснение заключается в том, что вы либо отправляете сообщение об объекте, который не был инициализирован, либо объекте, который уже был освобожден, но есть другие возможности.

Вы также можете посмотреть «So you crashed in objc_msgSend»; это написано о платформе Intel OS X, но большая часть ее также относится к ОС iPhone.

+0

Спасибо.Я уже прочитал сообщение, которое вы связали; вот как я научился смотреть на '$ r0' и' $ r1'. Адрес в '$ r0', являющийся' 0x3100000', очень подозрительно для меня. Учитывая все нули, я не думаю, что это очень вероятно, что это был действительный указатель на объект. –

2

Основываясь на вашей сессии gdb, кажется, что вы перевыпускаете какой-то объект, хотя я согласен с тем, что 0x3100000 кажется невероятным. Вы пытались запустить сборку и анализ? Статический анализ может уловить множество распространенных ошибок.

Основываясь на этом адресе памяти, переполнение буфера кажется более вероятным. Это также может объяснить, почему он сбой только в режиме выпуска при компиляции с -O2 или выше. Оптимизация может заключаться в том, что выкладываете свою память таким образом, чтобы переполнение буфера вызывало сбои в режиме деблокирования, но не в режиме отладки.

Вы делаете что-нибудь напуганное со старой школой C void * указатели? Работа с любыми нулевыми завершенными строками C? Выполнение любой арифметики указателя?

+0

Переполнение буфера кажется очень вероятным. Когда происходит сбой, я нахожусь в середине чтения с внешнего аксессуара. Это всегда происходит после некоторого количества чтений (я забываю точный номер ... что-то вроде 60). Многие мои низкоуровневые коды обработки пакетов используют буферы C-стиля, поэтому существует определенная вероятность переполнения буфера. Спасибо за идею! –

+0

Вы нашли это? – cduhn

 Смежные вопросы

  • Нет связанных вопросов^_^