动态安全检查

除了静态类型给我们提供的安全保证以外,仓颉同时也非常重视运行时的安全检查,对于一些不适合使用静态类型的场景,仓颉也提供了运行时检查的安全保证。

溢出检查

不同于大多数传统语言,在仓颉中的整数运算默认会进行溢出检查而不是任由其 wrapping。

当上下文足以静态分析的时候,整数溢出可提前在编译期检测出来,编译器会直接给出报错;当上下文不足以静态分析的时候,整数溢出会在运行时做一个检查,如果溢出会抛出运行时异常。

这个机制使得大多数时候,整数溢出都会及时被感知,避免造成业务隐患。

运行时检查会增加额外的计算开销,但经过仓颉编译器优化后可以将计算开销控制在一个较小的水平。

如果一些敏感场景希望通过接受 wrapping 的代价来换取更好的极限性能,也可以手动指定溢出策略来实现传统语言的行为。

@OverflowWrapping
func test(x: Int8, y: Int8) { // if x equals to 127 and y equals to 3
    let z = x + y // z equals to -126
}

数组越界检查

同样的,在仓颉数组的下标访问中,对数组的下标越界访问也有安全检查。当上下文足以静态分析的时候,下标访问可提前在编译期检测出来,编译器会直接给出报错;当上下文不足以静态分析的时候,下标访问会在运行时做一个检查,如果溢出会抛出运行时异常。

func f(index: Int) {
    let a = [1, 2, 3]
    let b = a[-1] // 编译期报错
    let c = a[index] // 运行时检查
}