用静态分析器尽早发现 Bug
Detect bugs early with the static analyzer
2021年6月10日
一句话判断
Xcode 13 的静态分析器加了几个新的检查规则,配合 Xcode Cloud 自动运行,等于免费多了一层代码审查。
这场 Session 讲了什么
Session 重点介绍了 Xcode 13 中 Clang 静态分析器的增强。静态分析器在编译期检查代码中的潜在问题,不需要运行代码就能发现空指针解引用、内存泄漏、未初始化变量等 Bug。Xcode 13 新增了若干检查规则,并改进了既有规则的准确性。
新增的检查包括:对 NSNumber 和 CFBoolean 混用的检测(两者在 ObjC 中不是同一个类型但容易混淆)、对 nil 作为集合元素插入的检测、以及对 dispatch_once 中可能的死锁检测。这些都是在实际项目中经常踩的坑。
Session 还建议将静态分析集成到 Xcode Cloud 的 CI 流程中。每次提交代码自动跑分析,问题会出现在 PR 的注释里。这样静态分析不再是”想起来才跑一次”的事情,而是持续的安全网。
值得深挖的点
NSNumber 和 CFBoolean 的隐秘陷阱
在 Objective-C 中,@YES 是一个 NSNumber 对象包装了布尔值 YES。但 CFBoolean 是 Core Foundation 的布尔类型。两者虽然底层都是 NSNumber,但在某些比较场景中行为不同——特别是 == 比较和 isEqual: 的结果可能不一致。静态分析器现在能检测到这种混用,防止出现”明明是 true 但比较结果为 false”的诡异 Bug。
静态分析在 CI 中的 ROI
很多团队不跑静态分析的原因是它慢。但实际上在 CI 中运行不需要开发者等待,而且静态分析发现的问题通常是真正的 Bug 而非风格问题。Session 展示了在 Xcode Cloud 中一条配置就能启用,投入产出比很高。尤其是对大型 ObjC 项目,这些新增检查能捕获到人工 code review 容易遗漏的细微问题。
代码片段
在 Xcode Cloud 中启用静态分析
# ci_scripts/ci_post_clone.sh
#!/bin/sh
# 在 CI 中运行静态分析
xcodebuild analyze \
-project MyProject.xcodeproj \
-scheme MyScheme \
-destination 'platform=iOS Simulator,name=iPhone 13' \
CLANG_ANALYZER_NONNULL=YES \
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION=YES
# 分析结果会出现在构建日志中
典型的 NSNumber/CFBoolean 问题
// Objective-C 中的常见陷阱
NSNumber *flag = @YES; // NSNumber 包装的布尔值
// 这个比较在某些情况下返回 NO,即使两者都是"true"
if ([flag isEqual:(__bridge NSNumber *)kCFBooleanTrue]) {
// 可能不会进入,因为内部表示不同
}
// 静态分析器会警告你使用更安全的比较方式
if (flag.boolValue) {
// 正确:通过 boolValue 获取原始布尔值
}
检测 nil 插入集合的问题
// 向 NSMutableArray 插入 nil 会崩溃
NSMutableArray *array = [NSMutableArray array];
NSString *value = nil; // 可能是函数返回的 nil
// 静态分析器会警告这一行
[array addObject:value]; // 如果 value 是 nil 就崩溃
// 安全写法
if (value) {
[array addObject:value];
}
最佳实践
新项目: 从第一天就在 Build Settings 中开启所有静态分析警告(Analyze During 'Build' = YES)。在 CI 中也配置自动运行。ObjC 项目把 CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION 打开。
已有项目: 先在 CI 中开启静态分析看看有多少现有警告。不要试图一次修完,按严重程度排优先级。空指针解引用和内存泄漏优先处理,NSNumber/CFBoolean 混用次之。可以在文件级别用 #pragma clang diagnostic 暂时压制已知问题的警告。
还有什么值得关注
- 静态分析器对 Swift 的支持仍然有限,主要收益在 Objective-C 项目中。
clang --analyze命令行工具可以脱离 Xcode 运行,方便集成到非 Xcode Cloud 的 CI 中。- Xcode 13 的 Issue Navigator 现在能更好地分组展示静态分析结果。