前言
EXC_BREAKPOINT (SIGTRAP)类型的异常大家都不陌生了,在其它资料上的解释: SIGTRAP代表陷阱信号。它并不是一个真正的崩溃信号。它会在处理器执行trap指令发送。LLDB调试器通常会处理此信号,并在指定的断点处停止运行。
那么关键的问题来了: 生产项目遇到这个问题的时候怎么解决。
问题
最近写了一个功能,写完之后、上线、发现有问题,这怎么办,影响用户的事情得尽快解决啊。于是在log中翻找了一通,找到了崩溃的函数堆栈看到最后调用的函数是下面这个函数
@objc func testA (_index:UInt) {
if index != currentIndex -1{
print("\(index)")
currentIndex = index
}
}
复现很难怎么办,项目首先就反应出来:是不是数字溢出,swift中的UInt和OC中的NSUInteger是不一样的 ,当发生溢出的时候UInt会直接崩溃,而NSInteger会循环生成最大的数值。于是分析了一顿函数的入参,各种情况都试了一次检验是不是入参数字溢出。 各种调试都不见效果。
解决方案
这个时候只能是又回过头去看崩溃堆栈,再看的时候发现了一个问题,在函数执行的时候。执行了另外一个函数
func testB () {
self.currentIndex = 0
}
于是,问题就明朗了。在我们调用这个函数之前,调用了testB函数。 这个时候currentIndex变成0。 这个时候testA函数执行,这个时候,判断条件右侧的表达式 currentIndex -1 就会报swift runtime failure:arithmetic overflow异常,这意味着发生了溢出,于是,应用程序就崩溃了。所以,遇到问题果然还是要先认真查找一下原因。另外,如果你收到了原因不明的SIGTRAP,先清除上次的输出,然后重新进行构建通常能解决这个问题。
结尾
数字溢出很常见的一个问题了。但是当发生的时候,往往表现形式不是我们所熟知的那种形式。平时写代码还是要多注意这个问题。另外如果真的希望swift中进行溢出运算可以使用&+、&-、&*这些运算符号。
网友评论