ios swift uiviewcontroller exc-bad-access swift-protocols

ios - IBOutlet se bloquea con EXC_BAD_ACCESS aunque no es nulo



swift uiviewcontroller (5)

En un UIViewController (rolePageController) configuro otro UIViewController (drawerController) y le paso 2 UIViews desde la página de roles que formará parte de la configuración del drawerController. Tan pronto como drawerController intenta acceder a las vistas de IBOutlet desde rolePageController, se bloquea con EXC_BAD_ACCESS (código = EXC_I386_GPFLT).

En el 1er VC (rolePageController), aquí están los IBOutlets:

@IBOutlet var rolePageDrawerView: UIView! @IBOutlet var rolePageContentView: UIView!

En rolePageController.viewDidLoad () hago una llamada al drawerController.configureDrawer (...):

override func viewDidLoad() { super.viewDidLoad() //other stuff happens here let drawerController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "drawerController") as! DrawerViewController drawerController.configureDrawer(drawerContainerView: self.rolePageDrawerView, overlaidView: self.rolePageContentView) //other stuff here }

El protocolo DrawerViewController se define como:

protocol DrawerViewController where Self: UIViewController { func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) }

Aquí está el código para la función configureDrawer (...):

private var drawerParentView: UIView! private var overlaidByDrawerView: UIView! func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) { self.drawerParentView = drawerContainerView self.overlaidByDrawerView = overlaidView }

Notó en el depurador que la instancia drawerController a la que se llama no coincide con la instancia propia que recibe la llamada. Aquí está la dirección de la instancia que será llamada:

Aquí está la dirección de la instancia cuando entro en la llamada:

La dirección de drawerController antes de la llamada no es la dirección de yo cuando entro en la llamada. Eso nunca debería suceder.

He creado un proyecto simplificado que reproduce el bloqueo en https://github.com/ksoftllc/DynamicStackBufferOverflow .

Solución La solución resultó ser eliminar la cláusula where del protocolo DrawerViewController.

protocol DrawerViewController where Self: UIViewController { func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) }


Encontré el código ofensivo, pero no sé por qué esto causaría los errores que estaba viendo. DrawerController cumple con el protocolo DrawerViewController, definido como:

protocol DrawerViewController where Self: UIViewController { func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) }

Cuando elimino la condición Where, ya no se bloquea.

protocol DrawerViewController { func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) }

La cláusula where no era realmente necesaria para el correcto funcionamiento del programa, por lo que procederé sin ella.

ACTUALIZACIÓN Presenté un error en swift.org y recibí una respuesta. La adición de una cláusula where a un protocolo no se admite en Swift 4.2, pero sí en Swift 5.0. Además, @J Doe publicó a continuación una forma de lograr esto con una actualización del kit de herramientas Xcode.


Mueva esta función Llamar de viewDidLoad a viewWillAppear drawerController.configureDrawer(drawerContainerView: self.rolePageDrawerView, overlaidView: self.rolePageContentView)


Para solucionar su problema, ejecútelo en la instantánea de la cadena de herramientas de la troncal de desarrollo. Puedes descargarlo aquí:

https://swift.org/download/

Vaya a Snapshots -> Trunk Development (master) XCode (así que no a Swift 5.0) y descargue la instantánea a partir del 15 de diciembre (obtuve la del 30 de noviembre, pero estoy seguro de que el 15 de diciembre también funcionará).

Después de instalar la cadena de herramientas, en XCode vaya a: File -> Preferences -> Components y seleccione la cadena de herramientas más nueva. Ahora se ejecuta sin ningún tipo de accidente .

Además, donde Self: UIViewController se puede reducir a :UIViewcontroller ( Esto solo funciona en las últimas cadenas de herramientas ):

protocol DrawerViewController: UIViewController { func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) }


Realmente se parece a Swift error compilador. Simplifiqué tu código de aclaración:

func foo(_ wow: TestProtocol) { wow.foo() } protocol TestProtocol where Self: NSObject { func foo() } class TestClass: NSObject, TestProtocol { func foo() { print("Much wow") } } foo(TestClass())

Puedes reportar esto como un error. Para resolver este problema, le propongo que no utilice el objeto where declaración o pass con su tipo func foo(_ wow: TestClass { .


dynamic-stack-buffer-overflow no tiene nada que ver con la recursión. Significa que un tampón de alloca fue invadido. Compruebe el código fuente de asan runtime .

Supongamos que la pila está dispuesta de modo que tenga un búfer de alloca seguido de un puntero de objeto, tal vez incluso uno de los punteros de objeto pasados ​​como argumento.

Supongamos que el búfer de alloca es invadido. En una compilación asan, esto puede desencadenar un error de dynamic-stack-buffer-overflow . Pero en una compilación no-asan, simplemente escribe sobre los bytes del puntero del objeto. Supongamos que escribe bytes que forman una dirección que no está asignada en la tabla de páginas de su proceso.

Si el programa intenta leer el puntero de ese objeto y almacenarlo en otro lugar (por ejemplo, en una variable de instancia), tiene que incrementar el conteo de referencia del objeto. Pero eso significa desreferenciar el puntero, y el puntero apunta a una dirección no asignada. Tal vez eso está llevando a una falla de protección general, que Mach llama un EXC_I386_GPFLT .

Sería útil si publicara el seguimiento de la dynamic-stack-buffer-overflow error asan dynamic-stack-buffer-overflow , y el desmontaje del código que conduce al error.