Apple Watch 在位操作上崩溃,错误代码为 Thread1:exc_breakpoint(code=exc_arm_breakpoint,subcode=0xe7ffdefe)

Apple Watch crashes on bit operations with error code Thread1: exc_breakpoint(code=exc_arm_breakpoint,subcode=0xe7ffdefe)

我在 Apple Watch 上使用 SHA1 散列用户数据,当 运行 SHA1Bytes 函数时,我收到以下错误:

Thread1: exc_breakpoint(code=exc_arm_breakpoint,subcode=0xe7ffdefe). This specific line gives me the error: j = ( UInt32((msg[i]<<24) | (msg[i+1]<<16) | (msg[i+2]<<8) | msg[i+3]) )

这是从中提取上述行的代码段:

class func SHA1Bytes(msg: [Int])->String{
        func rotateLeft(number: UInt32, rotateBy: UInt32)->UInt32{
            return ((number << rotateBy) | (number>>(32-rotateBy)))
        }

        func cvt_hex(value: UInt32)->String{
            var str = ""
            for i:UInt32 in stride(from: 7, through: 0, by: -1){
                let v: UInt32 = (value >> (i*4)&0x0f)
                str += String(v,radix: 16, uppercase: false)
            }
            return str
        }

        var W = [UInt32](repeating: 0, count: 80)
        var H0 = UInt32("67452301",radix: 16)!
        var H1 = UInt32("EFCDAB89",radix: 16)!
        var H2 = UInt32("98BADCFE",radix: 16)!
        var H3 = UInt32("10325476",radix: 16)!
        var H4 = UInt32("C3D2E1F0",radix: 16)!

        var wordArray = [UInt32]()
        for k in stride(from: 0, to: msg.count-3, by: 4) {
            let j = ( UInt32((msg[k]<<24) | (msg[k+1]<<16) | (msg[k+2]<<8) | msg[k+3]) )
            wordArray.append(j)
        }
        ...
        return encoded.uppercased()
    }

完全相同的代码在 iOS 游乐场中运行完美,但在第一代 Apple Watch 上 运行 时会崩溃。我已经检查过并且输入数组存在,我正在尝试访问它的现有元素并且 j 的结果不应该溢出。 该代码因以下变量值而失败:

j=(UInt32) 2308511418, k=(Int)48, msg=([Int])56values

这些是 msg 的值:

[47]    Int 217
[48]    Int 137
[49]    Int 153
[50]    Int 22
[51]    Int 186
[52]    Int 163
[53]    Int 41
[54]    Int 208
[55]    Int 104

第一代 Apple Watch 是 32 位设备,与 64 位设备相比具有不同的溢出限制。

在 32 位设备上,Int 类型是 32 位,您可能会转移到符号位。

在 playground 中尝试以下操作:

UInt32(Int64(153) << 24) // Equivalent to your code

UInt32(Int32(153) << 24) // Simulates a 32-bit device and crashes.

UInt32(153) << 24         // A possible solution

我设法弄清楚即使 UInt32 溢出,模拟器也不会崩溃,但是,在这种情况下,32 位 Apple Watch 确实会崩溃。 解决方案是使用一个溢出运算符,它只存在于加法、减法和乘法中。因此,我将按位左移更改为乘以 2^(要移位的位数)。 这是正确的解决方案:UInt32(msg[k])&*UInt32(1<<24)

let j = (UInt32(msg[k])&*UInt32(1<<24))|UInt32(msg[k+1]&*(1<<16))|UInt32(msg[k+2]&*(1<<8))|UInt32(msg[k+3])