iphone uiscrollview exc-bad-access

iphone - Accidente UIScrollView EXC_BAD_ACCESS en iOS SDK



exc-bad-access (9)

Tengo una aplicación para iPhone SDK que tiene varias vistas que aparecen y desaparecen a medida que el usuario crea contenido. Después de usar la aplicación en un dispositivo por un tiempo, recibo el siguiente bloqueo:

Program received signal: “EXC_BAD_ACCESS”. (gdb) backtrace #0 0x33369ebc in objc_msgSend () #1 0x320e5248 in -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded] () #2 0x338b4a14 in -[NSObject performSelector:withObject:] () #3 0x320e5098 in -[UIAnimator stopAnimation:] () #4 0x320e4b7c in -[UIAnimator(Static) _advance:] () #5 0x320e4a34 in LCDHeartbeatCallback () #6 0x34350e60 in HeartbeatVBLCallback () #7 0x332e91c0 in IOMobileFramebufferNotifyFunc () #8 0x316532f8 in ?? () #9 0x33866b50 in __CFMachPortPerform () #10 0x338ae52a in CFRunLoopRunSpecific () #11 0x338adc1e in CFRunLoopRunInMode () #12 0x3434e1c8 in GSEventRunModal () #13 0x32002c30 in -[UIApplication _run] () #14 0x32001230 in UIApplicationMain () #15 0x00002ff8 in main (argc=1, argv=0x2ffff550) at /Developer/svn/MyCompany/iPhone/MyApplication/Other Sources/main.m:14

Como puede ver en la traza, la única mención de mi código es la llamada a main.

He ejecutado Build and Analyze de Xcode, y también lo configuré para ejecutar el analizador de clang en mi proyecto desde la Terminal, y ninguno de los dos puede encontrar ningún problema en el código. Estoy usando una versión de lanzamiento muy reciente del iOS SDK (todavía no descargué el 4.1, pero el que estoy usando es el que estaba en lanzamiento justo antes de 4.1).

Además, he ejecutado la aplicación en Instruments with the Simulator, y la aplicación no tiene pérdidas de memoria.

Estoy a punto de tratar de usar la variable NSZombieEnabled y ver si eso encuentra algo, pero el problema es que necesito usar la aplicación durante 30 a 40 minutos antes de que se bloquee, y sospecho que NSZombieEnabled puede que ni siquiera me ayude a encontrar la cuestión.

Parece que los bloqueos que he visto se producen cuando una vista modal llama a un delegado en el controlador de vista principal. El controlador de vista principal luego procesa algo antes de descartar el controlador de vista modal. Hay algunas referencias en el choque a la animación y las vistas de desplazamiento, pero no estoy seguro de qué podría estar haciendo para causar problemas. ¿Alguien tiene alguna sugerencia de cosas que buscar?

EDITAR: He puesto el indicador NSZombieEnabled en la aplicación, y en el dispositivo aparece este mensaje en la consola:

2010-09-11 17:10:33.970 MyApplication[9321:207] *** -[MyViewController respondsToSelector:]: message sent to deallocated instance 0x7489480

Por lo que puedo decir, estoy configurando los delegados utilizados en la aplicación para que sean nulos en los desglose de todas mis clases, por lo que estoy atascado en cuanto a dónde mirar a continuación.

Traté de usar el malloc_history pid address en esto, pero decía que no podía encontrar el proceso, probé 9321, 9321: 207 y 207. Además, si trato de usar la variable MallocStackLogging , el programa no se ejecutará en el dispositivo, obtengo un montón de malloc: no se pueden crear mensajes de directorio de registro de pila en la consola y un bloqueo del programa.

Ah, y dicho sea de paso, no puedo usar los zombies que controlan los instrumentos, ya que no parece funcionar con un dispositivo, y no puedo obtener el mismo bloqueo en el simulador.


Acabo de solucionar este problema yo mismo.

Tuve un problema donde:

  • Un delegado de scrollview se conectó a un UIViewController
  • La vista de desplazamiento comenzó a animar
  • El delegado se fue y se llamó a dealloc.

El problema era que los mensajes delegados de scrollview estaban disparando en un objeto nuevo desasignado, y los registros de bloqueo eran un poco confusos ya que apuntaban a referencias de objetos sin sentido.

La solución fue establecer el delegado scrollview en nil como la primera línea de mi controlador de vista método dealloc.

¡Espero que esto ayude a alguien más!


Al principio, los delegados deben ser débiles / asignar tipo. Pero el evento en este caso es un obstáculo sutil muy común impulsado por animaciones de desplazamiento. Si usa cambios de desplazamiento de contenido animado para sus ScrollViews , necesita configurar su delegate a nil en el método dealloc .

De lo contrario, obtendrás lo siguiente

[YourViewController respondsToSelector:]: message sent to deallocated instance

El ejemplo muy común:

1. _tableView is ivar of YourViewController 2. _tableView.delegate = self; 3. - (void)scrollViewDidScroll:(UIScrollView *)scrollView is implemented at YourViewController 4. at some point you call [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; or [_tableView setContentOffset:CGPoint animated:YES] and try to close YourViewController

El _tableView es retenido por CoreAnimation, pero YourViewController está desasignado.


Después de enfrentar el mismo problema, establecí:

self.collectionView.delegate = nil;

in - (void)viewDidLoad (antes de configurar ViewController como delegado de collectionView) y -(void)viewWillDisappear:(BOOL)animated

Todo funciona bien ahora

Gracias por la ayuda.


El UIScrollView en el stack frame # 1 probablemente quiere informar a su delegado sobre la finalización de la animación, pero el delegado se ha ido en ese momento. Establecer NSZombieEnabled probablemente lo confirme.

Los delegados no se conservan, por lo que este es un error común en Cocoa y Cocoa Touch. Busque delegados en UIScrollView o UITableView en su código e intente descubrir cuál podría ser lanzado antes de tiempo.


Esto puede suceder si inserta un controlador de actualización en una vista de tabla como una subvista (mi pista, nunca lo haga) ...


He visto ese comportamiento cuando invoco scrollToRowAtIndexPath sin indexPath existente


Mi suposición sería que el delegado de scrollview está configurado a un objeto que ha sido desasignado. Intente configurar todos los delegados de los objetos secundarios a cero en sus métodos dealloc.


Para completarlo, estoy agregando este seguimiento de pila (iOS 6) para aquellos que pueden encontrar el mismo problema pero con una implementación un poco diferente y los pasos exactos para reproducir el problema.

Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x71f05631 Crashed Thread: 0 Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libobjc.A.dylib 0x3919b5d0 objc_msgSend + 1 1 UIKit 0x33421830 -[UIScrollView(UIScrollViewInternal) _delegateScrollViewAnimationEnded] + 48 2 UIKit 0x334217ba -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded:finished:] + 130 3 UIKit 0x334216a4 -[UIAnimator stopAnimation:] + 460

Esto está sucediendo en iOS 6 y comenzó a ocurrir cuando implementé el método UIScrollViewDelegate:

" -(void)scrollViewDidEndDecelerating:(UITableView *)tableView" and made a call to: "[tableView scrollToRowAtIndexPath: indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];".

El problema ocurrió cuando la animación comenzó y presioné el botón "Atrás" y mi controlador de vista se quitó antes de que la animación se completara.

Al reproducir, debe asegurarse de presionar el botón "Atrás" después de que comience la animación, pero antes de que se complete. Me tomó algunos intentos. Intenté recrear el problema apagando programáticamente el controlador de vista, pero no pude reproducirlo. Tuve que usar el botón "Atrás". Simplemente había estado llamando a [myTableView release] en el trato. La solución fue como se describe aquí para establecer ambas propiedades en cero:

self.myTableView.delegate = nil; self.myTableView = nil;


Todo lo anterior no solucionó mi problema, así que volví a cavar mi código. Reconocí que el bloqueo aparece cuando realizo el teclado y la animación UICollectionView (sí, es un chat) y descarto el controlador actual.

La aplicación se bloquea porque intento hacer un desplazamiento en el bloque de compleción de animación :)

¡Solo córtalo y todo funciona bien ahora!

Feliz codificación y depuración :)