一.Xcode Analyze静态分析 Static Code Analysis
Static Code Analysis(静态代码分析)用来发现源代码潜在的错误与缺陷,源代码编译后只有在运行时有可能会产生细微的错误,他们可能难以识别和修复,所以这些潜在的威胁在开发过程中一定要尽可能清理干净,尽量编写的时候注意类似可能潜在的威胁与缺陷
(点击查看苹果Static Code Analysis官方介绍)
二.可以识别的问题与缺陷
1.逻辑缺陷,如访问未初始化的变量和空指针
2.内存管理的缺陷,如分配后的内存泄漏
3.无效数据(未使用的变量)缺陷
4.使用api缺陷,不遵循库或者框架的使用规则
三.打开方式
1.Xcode顶部菜单Product-->Analyze即可开启
2.长按Xcode的run运行箭头选择Analyze即可开启
3.cmd + shift + b 快捷键开启
四.使用方法
1.左侧问题导航选择某一条蓝色警告分析
2.点击右侧源码编辑器的蓝色消息体
3.查看错误跟踪线
4.编辑代码修改错误
五.常见问题缺陷与解决办法
1.Passed-by-value struct argument contains uninitialized data (e.g., via the field chain: 'origin.x')
错误:
1 2 3 4 5 6 7 |
-(UIView*)test { CGRect rect; UIView *view = [[UIView alloc]init]; view.frame = rect; return view; } |
正确:
1 2 3 4 5 6 7 |
-(UIView*)test { CGRect rect = CGRectZero; UIView *view = [[UIView alloc]init]; view.frame = rect; return view; } |
2.Value stored to 'array' during its initialization is never read
变量申请了内存并初始化,但没有使用此变量,接着将此变量又重新赋值
错误:
1 2 3 |
NSMutableArray *array = [NSMutableArray array]; array = [responseObject objectForKey:@"result"]; ..... |
正确:
1 2 |
NSMutableArray *array = [responseObject objectForKey:@"result"]; ..... |
3.Value stored to 'array' is never read
变量'array' 未被使用
1 |
__unused NSMutableArray *array = @[@"1",@"2"]; //使用__unused或者注释掉 |
4. The 'viewWillAppear:' instance method in UIViewController subclass 'TempViewController' is missing a [super viewWillAppear:] call
错误
1 2 3 |
-(void)viewWillAppear:(BOOL)animated{ .... } |
正确
1 2 3 4 |
-(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; ..... } |
5.Assigned value is garbage or undefined
变量没有初始化就赋值给其他变量时会出现这个提示
6.Access to instance variable 'viewDelegate' results in a dereference of a null pointer (loaded from variable 'self')
如果self是nil,那么你不能访问self的实例变量 。所以应该引用这些变量在if self语句中,比如init方法中 当self不为nil方可使用
7.Potential leak of an object stored into 'imageRef'
CGImageRelease(imageRef)
CG开头的这些C-types对象使用过后都需要手动Release
8.Potential leak of an object
潜在的内存泄漏问题
9.Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected
10.Instance variable used while 'self' is not set to the result of '[(super or self) init...]'
错误
1 2 3 4 5 6 7 |
-(id)init { if(![super init]){ return nil; } return self; } |
正确
1 2 3 4 5 6 7 8 |
-(id)init { self = [super init]; if(!self){ return nil; } return self; } |
11.The left operand of '+' is a garbage value /The left operand of '-' is a garbage value
数据赋值隐患
12.Instance variable 'program' in class 'PLRenderer' is never used by the methods in its @implementation (although it may be used by category methods)
13.Key argument to 'setObject:forKey:' cannot be nil/Value argument to 'setObject:forKey:' cannot be nil
key或者value不能为nil
14.Incorrect decrement of the reference count of an object that is not owned at this point by the caller
变量申请了内存并初始化,但没有使用此变量,接着将此变量又重新赋值
15.Array access (from variable 's') results in a null pointer dereference
16.Dereference of null pointer
空指针引用
17.Argument in message expression is an uninitialized value
18.Function call argument is an uninitialized value
变量未进行初始化后被其他变量引用
错误
1 2 3 4 5 6 7 8 |
-(UIView*)test { CGRect rect; CGSize size; CGRect rectResult = CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height); UIView *view = [[UIView alloc]initWithFrame:rectResult]; return view; } |
正确
1 2 3 4 5 6 7 8 |
-(UIView*)test { CGRect rect = CGRectZero; CGSize size = CGSizeZero; CGRect rectResult = CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height); UIView *view = [[UIView alloc]initWithFrame:rectResult]; return view; } |
19.Division by zero
错误
1 2 3 4 5 6 |
NSUInteger measurements = [bandwidthUsageTracker count]; unsigned long totalBytes = 0; for (NSNumber *bytes in bandwidthUsageTracker) { totalBytes += [bytes unsignedLongValue]; } averageBandwidthUsedPerSecond = totalBytes/measurements; |
正确 加个非零判断
20.Receiver in message expression is a garbage value
要回收的变量接受到了消息
21.Argument to free() is offset by 2 bytes from the start of memory allocated by malloc()
22.Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil
参数可能为nil
1 2 3 4 5 6 7 |
NSCharacterSet *cs; if (textField == _text1) { cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS] invertedSet]; } else if (textField == _text2) { cs = [[NSCharacterSet characterSetWithCharactersInString:SIGNLESS_NUMBERS] invertedSet]; } NSArray *array = [string componentsSeparatedByCharactersInSet:cs]; |