Chu*_*ger 17 exc-bad-access uiviewcontroller ios swift swift-protocols
在UIViewController(rolePageController)中,我配置另一个UIViewController(drawerController)并从角色页面传递2个UIViews,该页面将成为drawerController配置的一部分.一旦drawerController尝试从rolePageController访问IBOutlet视图,它就会崩溃EXC_BAD_ACCESS(代码= EXC_I386_GPFLT).
在第一个VC(rolePageController)中,这里是IBOutlets:
@IBOutlet var rolePageDrawerView: UIView!
@IBOutlet var rolePageContentView: UIView!
Run Code Online (Sandbox Code Playgroud)
在rolePageController.viewDidLoad()中,我调用了抽屉控件.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
}
Run Code Online (Sandbox Code Playgroud)
DrawerViewController协议定义为:
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Run Code Online (Sandbox Code Playgroud)
这是configureDrawer(...)func的代码:
private var drawerParentView: UIView!
private var overlaidByDrawerView: UIView!
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) {
self.drawerParentView = drawerContainerView
self.overlaidByDrawerView = overlaidView
}
Run Code Online (Sandbox Code Playgroud)
在调试器中注意到,调用的drawerController实例与接收调用的self实例不匹配.这是将被调用的实例的地址:
这是我进入呼叫时实例的地址:
当我进入呼叫时,呼叫前抽屉控制器的地址不是自己的地址.这绝不应该发生.
我创建了一个简化的项目,通过https://github.com/ksoftllc/DynamicStackBufferOverflow重现崩溃.
解决 方案解决方案原来是从DrawerViewController协议中删除where子句.
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Run Code Online (Sandbox Code Playgroud)
找到了有问题的代码,但我不知道为什么这会导致我看到的错误.drawerController符合DrawerViewController协议,定义如下:
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Run Code Online (Sandbox Code Playgroud)
当我删除Where条件时,它不再崩溃.
protocol DrawerViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
Run Code Online (Sandbox Code Playgroud)
where子句对于程序的正确功能实际上并不是必需的,所以我将在没有它的情况下继续.
更新 我向swift.org提交了一个错误并收到了回复.Swift 4.2不支持在协议中添加where子句,但在Swift 5.0中将支持.此外,@ J Doe在下面通过更新Xcode工具包发布了一种方法来完成此任务.
dynamic-stack-buffer-overflow
与递归没有任何关系.这意味着alloca
缓冲区溢出.检查asan运行时源代码.
假设堆栈已布局,以便您有一个alloca
缓冲区,后跟一个对象指针 - 甚至可能是作为参数传递的一个对象指针.
假设alloca
缓冲区溢出.在asan构建中,这可能会触发dynamic-stack-buffer-overflow
错误.但是在非asan构建中,它只是写入该对象指针的字节.假设它写入的字节构成了一个未映射到进程页表中的地址.
如果程序试图读取该对象指针并将其存储在别处(例如,在实例变量中),则必须增加对象的引用计数.但这意味着取消引用指针 - 指针指向未映射的地址.也许这会导致一般的保护错误,马赫称之为EXC_I386_GPFLT
.
如果您发布了asan dynamic-stack-buffer-overflow
错误的堆栈跟踪以及导致错误的代码的反汇编,那将会很有帮助.
归档时间: |
|
查看次数: |
656 次 |
最近记录: |