在UIViewController(rolePageController)中,我配置了另一个UIViewController(drawerController),并从角色页面向其传递2个UIViews,这将是抽屉控制器配置的一部分。一旦抽屉控制器尝试从rolePageController访问IBOutlet视图,它就会崩溃并显示EXC_BAD_ACCESS(code = EXC_I386_GPFLT)。
在第一个VC(rolePageController)中,这是IBOutlets:
@IBOutlet var rolePageDrawerView: UIView!
@IBOutlet var rolePageContentView: UIView!
在rolePageController.viewDidLoad()中,我调用了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
}
DrawerViewController协议定义为:
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
这是configureDrawer(...)函数的代码:
private var drawerParentView: UIView!
private var overlaidByDrawerView: UIView!
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView) {
self.drawerParentView = drawerContainerView
self.overlaidByDrawerView = overlaidView
}
在调试器中指出,所调用的抽屉控制器实例与接收该调用的自身实例不匹配。这是将被调用的实例的地址:
这是我步入通话时实例的地址:
当我进入该调用时,调用之前抽屉控制器的地址不是自己的地址。那永远不会发生。
我创建了一个简化的项目,可以复制https://github.com/ksoftllc/DynamicStackBufferOverflow处的崩溃。
解决方案 原来的解决方案是从DrawerViewController协议中删除where子句。
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
答案 0 :(得分:8)
找到了令人反感的代码,但是我不知道为什么这会导致我看到的错误。抽屉控制器符合DrawerViewController协议,定义为:
int magnitude = (int)Math.Pow(10, (int)Math.Log10(value));
当我删除Where条件时,它不再崩溃。
protocol DrawerViewController where Self: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
where子句对于程序的正确功能实际上并不是必需的,因此我将在没有它的情况下继续进行。
更新 我向swift.org提交了错误,并收到了回复。 Swift 4.2不支持在协议中添加where子句,但是Swift 5.0将支持添加子句。此外,@ J Doe在下面发布了一种通过更新Xcode工具包来实现此目的的方法。
答案 1 :(得分:5)
dynamic-stack-buffer-overflow
与递归无关。这意味着alloca
缓冲区已溢出。检查asan runtime source code。
假设堆栈布局合理,这样您就有一个alloca
缓冲区和一个对象指针,甚至可能是作为参数传递的对象指针之一。
假设alloca
缓冲区溢出。在asan构建中,这可能会触发dynamic-stack-buffer-overflow
错误。但是在非asan的构建中,它仅覆盖该对象指针的字节。假设它写入的字节构成了未在进程的页表中映射的地址。
如果程序尝试读取该对象指针并将其存储在其他位置(例如,在实例变量中),则它必须增加该对象的引用计数。但这意味着取消对指针的引用,并且指针指向未映射的地址。也许这会导致一般性保护错误,Mach calls an EXC_I386_GPFLT
。
如果您发布了asan dynamic-stack-buffer-overflow
错误的堆栈跟踪信息,并且对导致错误的代码进行了反汇编,将会很有帮助。
答案 2 :(得分:3)
它看起来确实像Swift编译器错误。为简化起见,我简化了代码:
func foo(_ wow: TestProtocol) {
wow.foo()
}
protocol TestProtocol where Self: NSObject {
func foo()
}
class TestClass: NSObject, TestProtocol {
func foo() {
print("Much wow")
}
}
foo(TestClass())
您可以将其报告为错误。为解决此问题,我建议您不要使用where语句或类型为func foo(_ wow: TestClass {
的pass对象。
答案 3 :(得分:0)
要解决您的问题,请在开发主干工具链快照上运行它。您可以在这里下载:
转到快照-> Trunk开发(主) XCode (不是Swift 5.0)并下载截至12月15日的快照(我从11月30日获得了快照,但是我确定12月15日也可以。)
安装工具链后,在XCode中转到:File -> Preferences -> Components
并选择最新的工具链。 它现在可以正常运行了。
此外,Self: UIViewController
的位置可以缩短为:UIViewcontroller
(这仅适用于最新的工具链):
protocol DrawerViewController: UIViewController {
func configureDrawer(drawerContainerView: UIView, overlaidView: UIView)
}
答案 4 :(得分:-2)
将此函数调用从viewDidLoad移动到viewWillAppear
nonmatch <- df[grepl("[^A-Za-z0-9[:punct:][:space:]]", df$text), ]