(iOS) a bug that made me look for 6 hours

0x0 bug description

Bug is like this, the program in the debug mode is normal, but packaged into IPA after the installation to iPhone5s and iPhoneSE (iPhone5 and its models do not try, do not know will not.) Bug has appeared on the phone. The following figure:

(iOS) a bug that made me look for 6 hours

As shown, click on the cell card for a long time, the page to jump.

0x1 looking for bug

Bug is packaged into a IPA only after the emergence, if only after the completion of each debugging and then installed on the phone to verify the phone, then in the process of looking for bug will be very cumbersome and time-consuming. Debug status from Debug to Release mode. Operation as follows:

Step 1

(iOS) a bug that made me look for 6 hours
Debug switch to Release

Step 2

(iOS) a bug that made me look for 6 hours
Debug switch to Release

After the completion of the direct run is release mode. Run the program again and found no Caton.
this pit father, looking for a long time did not find the problem in the wrong. There are other ways.

Open artifact Instruments select Core Animation, select the project to run the program and found that when entering the page when the use of CPU surge, it should be and UI interface, will lead to Caton.
can only be used to annotate + repeat packaging. After repeated comments test found that the code appears in the UICollectionView above, collectionView related code is as follows:

CGFloat = cellWidth ([UIScreen mainScreen].bounds.size.width - kLeftEdge - kRightEdge - 2*kCellItemSpacing) /3; _cellSize = CGSizeMake (cellWidth, kCellHeight); UICollectionViewFlowLayout *layout [[UICollectionViewFlowLayout = alloc]init]; layout.itemSize = _cellSize; layout.sectionInset = UIEdgeInsetsMake (kTopEdge, kLeftEdge, kBottomEdge, kRightEdge); layout.minimumInteritemSpacing = kCellItemSpacing; layout.minimumLineSpacing = kCellRowSpacing; _collectionView = UICollectionView + alloc]initWithFrame:CGRectMake (0, 0 [UIScreen, mainScreen].bounds.size.width, _collectionHeight) collectionViewLayout:layout]; _collectionView.showsHorizontalScrollIndicator = NO; _collectionView.backgroundColor = [UIColor whit EColor]; _collectionView.dataSource = self; _collectionView.delegate = self; _collectionView.scrollEnabled = NO; [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kCollectionIdentifier] [_collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader; withReuseIdentifier:kCollectionReusableViewHeader] [_collectionView; registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:kCollectionReusableViewFooter]; [self.view addSubview:_collectionView]; #pragma mark - UICollectionViewDelegate, UICollectionViewDataSource - (UICollectionViewCell * (UICollectionView * collectionView) collectionView:) cellForItemAtIndexPath: (NSIndexPath *) indexPath{UICollectionViewCell *cell dequeueReusableCellWithReuseIdentifier:kCollectionIdentifier forIndexPath:indexPath] return = [collectionView; cell;} - (UICollectionReusableView *) collectionView: (* UICollectionView) collectionView viewForSupplementaryElementOfKind: (NSString * kind) atIndexPath: (NSIndexPath *) indexPath{if ([kind isEqualToString:UICollectionElementKindSectionHeader) {UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kCollectionReusableViewHeader forIndexPath:indexPath]; for (UIView *subView in view.subview S {[subView removeFromSuperview]}); / / view.backgroundColor [ThemeManager colorForKeyPath:@ = "WhiteColor"]; view.size = CGSizeMake (LYScreen_Width, 30); UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake (12, 0, LYScreen_Width, 30); titleLabel.font = LYFont; titleLabel.textColor = [UIColor (12) LY_ColorWithHexString:@ 999999]; LYChargeDetailModel *model = _model.content[indexPath.section]; titleLabel.text = model.title; [view addSubview: titleLabel]; return view;}else{UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:kCollectionReu SableViewFooter forIndexPath:indexPath]; / / view.backgroundColor [ThemeManager colorForKeyPath:@ = "SpaLineColor"]; view.size = CGSizeMake (LYScreen_Width, 1.0f/[UIScreen, mainScreen].scale); return view;}} - (NSInteger): collectionView (UICollectionView *) collectionView numberOfItemsInSection: (NSInteger) section{LYChargeDetailModel *model = _model.content[section]; return model.items.count;} - (NSInteger) numberOfSectionsInCollectionView: (UICollectionView *) collectionView{return _model.content.count;} - (CGSize) collectionView: (UICollectionView * collectionView) layout: (UICollectionViewLayout *) collectionViewLayout referenceSizeForHeaderInSection: (NSInteger section{return CGSizeMake (LYScreen_Wid) Th, 30);} - (CGSize) collectionView: (UICollectionView * collectionView) layout: (UICollectionViewLayout *) collectionViewLayout referenceSizeForFooterInSection: (NSInteger) section{return CGSizeMake (LYScreen_Width, 1.0f/[UIScreen, mainScreen].scale);}

There is nothing wrong with the code, and then line by line. When the note is found to be _collectionView.dataSource = self; when the card is not, but UICollectionView did not content, and then check all the code under UICollectionViewDataSource. Or not found abnormal. Pick up the trouble, began to line up to see the code (this code is not my writing… Finally, when I saw a piece of code, I found an exception.

- (void) setModel: (LYChargeModel *) model{... CGFloat height for (int; I = 0; i< model.content.count; i++) {LYChargeDetailModel *detailModel NSInteger = model.content[i]; row = detailModel.items.count/3; row = (detailModel.items.count%3)? 1:0; height + = kCellHeight * row + kCellRowSpacing* (row - 1) + kTopEdge + kBottomEdge + 30}; NSInteger address = (NSInteger) (& height); self.title [NSString stringWithFormat:@ = "v:%0.f a:%li", height, address]; _collectionHeight = height;}...

Release mode to run the program and found that the numerical value of _collectionHeight anomalies become very large. Carefully check the height variables and did not give the initial value, the initial value of the height, packaged again found good, not card. So why does it cause the main thread to die when the value becomes large? So I did an experiment to assign height to MAXFLOAT. Packed again to the phone, found in the jump when the card dead. So you can guess when the collectionView is too large in reload will lead to the main thread card, bug perfect repair.

0x2 investigate its roots

Bug is the root of the CGFloat variable is not set the initial value which is normal and only in the Release mode in the next will appear in the Debug mode, that is to say the initial value of CGFloat in the Debug mode and Release mode value is different. (on iPhone5s or iPhoneSE devices).
then did an experiment and found that the default values for CGFloat in Debug and Release were 0, but there was a numerical exception if there was an additive operation.
code is as follows

CGFloat floatValue; NSMutableString *text = @ "/n".MutableCopy; [text "appendFormat:@ CGFloat Default:%f/n", floatValue] floatValue+=100; [text appendFormat:@; "CGFloat +100:%f/n", floatValue] CGFloat Default:0.000000 CGFloat +100:100.000000; //Debug printing //Release printing CGFloat Default:0.000000 CGFloat +200:100.000000

Obviously there is an exception in the Release state. Is there any difference in the value of the other numeric types in Release mode? Do the experiment.


NSInteger integer; CGFloat floatValue; int i; float f; double D; NSMutableString *text.MutableCopy; [text = @ "" appendFormat:@ "NSInteger default:%li/n", "CGFloat default:%f/n [text integer]; appendFormat:@ floatValue]; [text appendFormat:@", "int default:%i/n," i] [text appendFormat:@ "; float default:%f/n, f] [text appendFormat:@ double default:%f/n"; "d], integer+=1; floatValue+=1; i+=1; f+=1; [text; d+=1; appendFormat:@" NSInteger +1:%li/n "," CGFloat +1:%f/n [text integer]; appendFormat:@ floatValue]; [text appendFormat:@ "," int +1:%i/n, "i] [text appendFormat:@"; float f]; [text appendFormat:@ +1:%f/n "," double +1:%f/n ", d] NSLog ("% @ @; ", text);

IPhone SE

Under the condition of //Debug NSInteger default:2 CGFloat default:0.000000 / / Numerical numerical abnormality of int default:1// float default:129753328198464616092303097856.000000// double numerical abnormality default:0.000000 NSInteger +100:102// abnormal abnormal CGFloat +100:100.000000 int +100:101// float +100:129753328198464616092303097856.000000// double +100:100.000000 abnormal abnormal value under the condition of //Release Numerical numerical value NSInteger default:5533341776// numerical abnormality of CGFloat default:0.000000 int default:1238374480// float default:0.000000 double default:0.000000 NSInteger +100:5533341776// abnormal abnormal CGFloat abnormal +100:200.000000// int +100:0// float +100:200.000000// double +100:200.000000// abnormal abnormal abnormal value

IPhone 6

Abnormal CGFloat numerical value NSInteger default:2// CGFloat default:0.000000 int default:1// numerical abnormal abnormal float default: 137800089569547039707794243584.000000// double default:0.000000 NSInteger +100:102// CGFloat abnormal abnormal numerical value NSInteger default:2// numerical abnormality of CGFloat default:0.000000 int default:1// float default:137800089569547039707794243584.000000// double default:0.000000 NSInteger abnormal abnormal +100:102// //Debug state +100:100.000000 int +100: numerical 101// float +100:137800089569547039707794243584.000000// double +100:100.000000 //Release abnormal abnormal state values of +100:100.000000 int +100:101// float +100:137800089569547039707794243584.000000// double +100:100.000000 abnormal abnormal

Most of the values are found to be abnormal. It is worth noting that the two types of CGFloat and double always appear at the same time, the problem to the bottom of the CGFloat iOS is not implemented with double? So check the API found that CGFloat is defined as typedef CGFLOAT_TYPE CGFloat;.
CGFLOAT_TYPE what is this macro, access to information is not found, know the big brother said. Be deeply grateful。

If the CGFloat Relaese mode in iPhone5s and iPhoneSE does not set the default value for the addition operation will be abnormal, so that CGRect CGSize, CGPoint, in addition does not set the initial value of the condition will also have problems.


CGSize size; CGRect rect; CGPoint point; NSMutableString *text = @ "/n".MutableCopy; [text "appendFormat:@ CGSize default:%@/n", NSStringFromCGSize (size)]; [text appendFormat:@ "CGRect default:%@/n", NSStringFromCGRect (rect)]; [text appendFormat:@ "CGPoint default:%@/n", NSStringFromCGPoint (point)]; size.width+=100; size.height+=100; rect.size.width+=100; rect.size.height+=100; rect.origin.y+=100; rect.origin.x+=100; point.y+=100; point.x+=100; text [appendFormat:@ "CGSize +100:%@/n", NSStringFromCGSize (size)]; [text appendFormat:@ "CGRect +100:%@/n", NSStringFromCGRect (rect)]; [text appendFormat:@ "CGPoint +100:%@/n", NSStringFromCGPoint (point)];

IPhone SE

//Debug CGSize default:{4.9406564584124654e-324, 3.049280293648331e-314} CGRect default:{{0, 0}, {2.6509482737098556e-314, 3.337809125940193e-314}} CGPoint default:{0, 0} CGSize +100:{100, 100} CGRect +100:{{100, 100}, {100, 100}} CGPoint +100:{100, 100} //Release CGSize default:{0, 0} CGRect default:{{nan, 2.1219957904712067e-314}, {7.9499288951273625e-275, 0}} CGPoint default:{nan, 2.1219957904712067e-314} CGSize +100:{200, 200} CGRect +100:{{200, 200}, {200, 200}} CGPoint +100:{200 200}.

According to the results, in the Release mode CGRect, CGSize, CGPoint does not assign addition operations will appear abnormal.

0x3 conclusion

Numeric types must be given an initial value before the operation.