IOS Crash killer ranking

With the number of APP users toot toot ox up, the collapse of the problem is also up, the last few days was finally, time to focus on treatment of the collapse of the problem, we summarize, we hope to help.

Killer NO.1

NSInvalidArgumentException anomaly

There are many reasons for the emergence of the crash, select the number of crashes crash.

Crash log 1-1

-[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to nil object from insert objects[3]

Crash log to get, how to reproduce the phenomenon? We see initWithObjects:forKeys:count:, guess should be NSDictionary initialization problem, look at the back of the attempt to in insert nil object tips, you can make a guess at this point, should be the abnormal NSDictionary initialization caused by the insertion of nil objects. Below we write a code to verify:

NSString *password = nil; NSDictionary = *dict @{@ @ "userName": "Bruce", "password": @ password}; NSLog (@ dict is:% @ ", Dict);

After running, the crash information is as follows:

IOS Crash killer ranking
Crash log 1-1

The information above is a proof of our guess. From the crash log, the query to the problem of the crash log has 33 (total crash record 304), accounting for 10.85%, the crash rate is relatively high. Why is there such a phenomenon? How to solve this kind of crash?

The collapse rate high reason is because their framework adopts the design idea to model, not to return backstage data into model, but through a reformer mechanism into NSDictionary form, provide to the target object, in the NSDictionary conversion process, the returned data sometimes may be empty it will cause, insert the nil object, which can lead to crash.

There are 3 solutions to the problem:

Program 1: background in the return of the data when the checksum, the null value for processing. However, some of the null values in the project are for special purposes, which is not feasible.

Program two: when converted into NSDictionary, the background of the returned data to verify that the null value into a NSNull object. The program is feasible, but the need to make changes to the existing code, each time the conversion needs to be verified, too much trouble. Rapid development of the business, so the cost is too high.

Solution three: there is no need to change the existing code can solve the problem? The answer is yes, you can use the Objective-C runtime to solve the problem.

NSDictionary insert the nil object will cause collapse, but insert the NSNull object is not caused by the collapse of the runtime Swizzle Method, as long as the use of the nil object to the NSNull object can be converted into the problem to solve. Create a NSDictionary category, the use of runtime Swizzle Method to replace the system approach. Source code can refer to the Glow team package NSDictionary+NilSafe (Github can be downloaded to), all the source code will be provided at the end of the article, which is part of the interception code as follows:

(instancetype) + gl_dictionaryWithObjects: (const ID objects forKeys: []) (const id< NSCopying> []) keys count: (NSUInteger) CNT safeObjects[cnt] ID {ID; safeKeys[cnt]; NSUInteger J for (NSUInteger = 0; I = 0; I < CNT; i++) {ID key id = keys[i]; obj = objects[i]; if (! Key) {continue}; if (! Obj) {obj [NSNull} = null]; safeKeys[j] = key; safeObjects[j] = obj; j++; return [self gl_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j}]};

Crash log 1-2

Data parameter is nil

Through the log information, the collapse of the problem to the parameters for the nil, read the log information under the stack, the localization problem when the NSJSONSerialization serialization of the incoming data nil, caused the collapse of the. In order to verify that the problem is not, I wrote a piece of code to do the next verification:

NSData *data = nil; NSError *error; NSDictionary *orginDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:& error]; NSLog (@ originDict is:% @ ", orginDict);

After running, the crash information is as follows:

IOS Crash killer ranking
Crash log 1-2

This is a good solution to the problem, in the time of serialization, the uniform join judgment to determine whether data is nil.

Crash log 1-3

Unrecognized selector to instance sent 0x15d23910

The cause of this collapse, presumably we are more familiar with, that is, a class called a method that does not exist, resulting in collapse. To solve this problem, you can write a method, to determine the type of its class, do not conform to the type of call, you can also use the runtime common method to do the wrong. For example, I often have such a collapse:

-[__NSCFConstantString objectForKeyedSubscript:]: unrecognized selector sent to instance 0x1741af420 -[NSNull length] unrecognized selector sent to instance 0x1b21e6ef8: -[__NSCFConstantString objectForKeyedSubscript:]: unrecognized selector sent to instance -[__NSDictionaryI length] selector sent to instance 0x174264500: unrecognized

When these objects call these methods that do not exist, the replacement of their own definition of a method for them to make a mistake, so that the application will not collapse. Interception is part of the code, all the source code will be provided at the end of the article.

@implementation NSString (NSRangeException) + (void) load{static dispatch_once_t onceToken; dispatch_once (& onceToken, @autoreleasepool ^{{[objc_getClass ("__NSCFConstantString") swizzleMethod:@selector (objectForKeyedSubscript:) swizzledSelector:@selector (replace_objectForKeyedSubscript:)];}});} - (ID) replace_objectForKeyedSubscript: (NSString * key) {return nil}; @end

Summary of the NSInvalidArgumentException anomaly caused by the following reasons:

  • NSDictionary insert nil object. The same goes for NSMutableDictionary.
  • NSJSONSerialization serialization, the introduction of data to nil.
  • An unrecognized selector unrecognized method

NSInvalidArgumentException’s crash record has 149 (total crash record of 304), accounting for 49.01%, dominate the Crash sector, the killer ranked first.

Killer NO.2

SIGSEGV anomaly

SIGSEGV is when the SEGV occurs, so that the code to terminate the logo. This exception occurs when accessing memory that has not been opened or a memory that has been freed. In addition, in low memory, may also produce such an exception.

For this anomaly, we can use two ways to solve, a way of using Xcode built-in memory analysis tool (Leaks), an automation tool provided by the use of Facebook to monitor the memory leak problem, such as:
FBRetainCycleDetector, FBAllocationTracker, FBMemoryProfiler

Example 1:

DataOut = malloc (dataOutAvailable * sizeof (uint8_t));

This is the use of Xcode with Leaks tools to detect memory leaks, the code we see that this is a C language using the malloc function to allocate a block of memory address, but when not in use but forgot to release the memory address, thus causing a memory leak, should be when it does not use the following code plus:

Free (dataOut);

In addition, through this example we have to pay special attention to the use of C language objects, we must remember to release when not in use, ARC can not release the memory.

Example 2:

Can't add as subview self crash

The cause of the collapse, one reason is that when the push or pop of a view, and set up animated:YES (animated), if the animation is not complete, this time, you go to push or pop in another view, it will cause the abnormal. There are other reasons for this crash, for example:

[self.view addSubview:self.view];

To reproduce this phenomenon, I wrote the following code test, as follows:

- (IBAction) btnAction: (ID) sender *test01 alloc] init] {UIViewController = [[UIViewController; [self.navigationController pushViewController:test01 animated:YES]; [self.navigationController pushViewController:test01 animated:YES];}

The easiest way to solve this exception is to set the animated to NO, but it is not friendly, the system comes with the animation to remove the. Another friendly way is through the runtime to achieve, through a safe way to ensure that when the controller is in the stack or stack, no other stack or stack operation. Specific source code will be provided at the end of the article.

There are 57 crashes in SIGSEGV (a total of 304 crashes), accounting for about 18.75%. Ranked second in the Crash sector.

Killer NO.3

NSRangeException anomaly

This is caused by abnormal exception, we often encounter in the iOS exception has two kinds, one is the array bounds, a string interception border, we come to a concrete analysis through the crash log.

Crash log 3-1

-[__NSArrayM objectAtIndex:]: index 1 beyond for array -[__NSCFConstantString substringToIndex:]: Index 10 out of bounds; string length 0; empty bounds

Through the log can clearly know that the problem is caused by cross-border, reproduce the phenomenon is relatively simple, in the past. How to solve it?

Program 1: in the array of data, to determine the length of the array is greater than the index, which should be in the usual code to write when the specification. Also in the string interception, also need to do a similar judgment. But the reality is that sometimes we forget to write such a logical judgment, there will be a potential crash problem. How to do a unified judgment? Even if the developer forgot to write such a logical judgment will not cause a collapse, from the framework level to prevent this kind of collapse, program two gives the answer.

Program two: the use of runtime Swizzle Method features can be achieved from the framework of the level of this type of collapse to stop the problem, there are two advantages to do so:

  1. Developers forget to write the logic to determine the boundaries, it will not cause the collapse of app, transparent for developers.
  2. Do not need to modify the existing code, the invasion of the existing code to reduce the minimum, do not need to add a large number of redundant logic to determine the code.

All source code will be provided at the end of the article, the interception of part of the code:

@implementation NSArray (NSRangeException) + (void) load{static dispatch_once_t onceToken; dispatch_once (& onceToken, @autoreleasepool ^{{[objc_getClass ("__NSArray0") swizzleMethod:@selector (objectAtIndex:) swizzledSelector:@selector (emptyObjectIndex:)]; [objc_getClass ("__NSArrayI") swizzleMethod:@selector (objectAtIndex:) swizzledSelector:@selector (arrObjectIndex:)]; [objc_getClass ("__NSArrayM" (objectAtIndex: swizzleMethod:@selector) swizzledSelector:@selector) (mutableObjectIndex:)]; [objc_getClass ("__NSArrayM") swizzleMethod:@selector (insertObject:atIndex:) swizzledSelector:@selector (mutableInsertObject:atIndex:)];}});} - (ID) emptyObjectIndex: (NSInteger) Index{return nil;} - (ID) arrObjectIndex: (NSInteger) index{if (index > index < = self.count ||; 0) {return} nil; return [self arrObjectIndex:index];} - (ID) mutableObjectIndex: (NSInteger) index{if (index > index < = self.count ||; 0) {return nil;} return [self mutableObjectIndex:index];} - (void) mutableInsertObject: (ID) object atIndex: (NSUInteger) index{if (object) {[self mutableInsertObject:object atIndex:index]}}; @end

The collapse of the collapse of the record 46 (a total breakdown of the record is 304), accounting for 15.13%, ranking crash killer in the world ranking of third.

Killer NO.4

SIGPIPE anomaly

To explain what is abnormal SIGPIPE, popular point is the description of this: close to an end has socket call write two times, second times write will produce SIGPIPE signal, the signal end of the default process.

How to solve the problem? The SIGPIPE signal can be captured, it can be ignored, for the iOS system, just put the following code in the.Pch file can be.

#if defined only support SO_NOSIGPIPE / / IOS system (SO_NOSIGPIPE) & & defined! (MSG_NOSIGNAL) do not want SIGPIPE / / We if writing to socket. const int value = 1; setsockopt (FD, SOL_SOCKET, SO_NOSIGPIPE, & value, sizeof (int)); #endif

There are 11 crashes in SIGPIPE (a total of 304 crashes), accounting for about 3.61%. Ranked fourth in the Crash sector.

Killer NO.5

SIGABRT anomaly

This is a process that allows the termination of the logo, the assertion, app, the operating system with the termination method to throw. Occurs when an asynchronous execution of the system method. Such as CoreData, NSUserDefaults, etc., there are some other system multi-threaded operation.

Note: this does not necessarily mean that the system code exists bug, the code is only invalid or abnormal state.

SIGABRT crash log 9 (a total of 304 crash records), accounting for 2.96%. Crash ranks fifth.

Killer summary

In front of the 5 crash killer, accounting for 89.46% of the crash rate, to solve the crash killer, basically, your app is very strong, and the rest of the collapse of the problem requires specific analysis of specific issues.

Source download

http://zhijianshusheng.github.io/2016/07/11/%E6%8C%89%E5%91%A8%E5%88%86%E7%B1%BB/20160711-0718/%E5%AF%BC%E8%87%B4iOS%E5%B4%A9%E6%BA%83%E7%9A%84%E6%9C%80%E5%B8%B8%E8%A7%815%E5%A4%A7%E5%85%83%E5%87%B6/
https:// the code.facebook.com/posts/583946315094347/automatic-memory-leak-detection-on-ios/
http://tech.glowing.com/cn/how-we-made-nsdictionary-nil-safe/
http://stackoverflow.com/questions/19560198/ios-app-error-cant-add-self-as-subview
https://my.oschina.net/moooofly/blog/474604
http://devma.cn/blog/2016/11/10/ios-beng-kui-crash-jie-xi/

People of plum

We welcome the attention people of plum, accompany you on the road with technology.

IOS Crash killer ranking
guoshimeihua.jpg