How to fix a long crash of NSString?

In the application I'm working on, I read the numerical values ​​from a text file in a for loop, then do some calculations and add the result to the result line.

The file has 22050 values. I noticed that over some number of added loops / values ​​(~ 5300) it tends to crash.

I thought that maybe I have a memory leak, so I got rid of adding a line and everything worked fine. I tried to get rid of everything except adding a line, and the application crashed. I have a breakpoint in all exceptions, and I don't get any exceptions.

I wanted to make sure I started a new project. All I put is one UIButton, which, when clicked on, calls this piece of code:

- (IBAction)TestPressed:(id)sender { NSString *testString = @""; for (int i = 0; i < 22050; i++) { testString = [testString stringByAppendingString:@"12.34567890\n"]; } NSLog(@"%@", testString); } 

I have a breakpoint on the NSLog line. The application crashes.

Is there a limit on the length of an NSString? Does he use too much memory?

+4
source share
3 answers

The problem is that you create a new line at each iteration. There are two options to fix this: either use a mutable string to create the result:

 NSMutableString *testString = [NSMutableString string]; for (int i = 0; i < 22050; i++) { [testString appendString:@"12.34567890\n"]; } NSLog(@"%@", testString); 

... or use the autostart pool to delete instances in a loop:

 NSString *testString = @""; for (int i = 0; i < 22050; i++) { @autoreleasepool { testString = [testString stringByAppendingString:@"12.34567890\n"]; } } NSLog(@"%@", testString); 

Please note that I included the second version only to show why the problem arose in the first place and how to fix it. It is still inefficient, as it creates 22049 temporary lines with an average length of 120,000 characters.

+13
source

Use NSMutableString to add lines, otherwise too much memory is allocated.

+2
source

+[NSString stringByAppendingString:] creates a new, auto-implemented object every time you call it. Authorized objects are not freed until an autocomplete pool appears, which usually means at the end of an event loop. In this case, it is best to use NSMutableString as other answers indicate. But if you encounter a problem when you need to create many objects with auto-implementation instead of using a mutable object, you can wrap the @autoreleasepool {} block around the code that creates the objects so that you do not have massive memory to swell, but you have to be careful. to save objects that you want to stick out of @autoreleasepool .

In general, I try to avoid using auto-implemented objects as much as possible for several reasons:

1) When objects are actually freed, it can be non-deterministic if you actually do not have an autostart pool in your method itself. Otherwise, there is no way to find out the size of the auto settlement pool, and when the calling code decides to fill the pool.

2) Autorealizators are inherently more resource intensive than manual release. Objects must be added to the pool, then repeated and released later.

3) Auto-implementers become especially complex in a multi-threaded environment, because often you can race between threads that free an object. In these situations, it is easy to create an intermittent failure scenario that is difficult to reproduce or find the root cause.

4) Failure, as a rule, is much more difficult to analyze when working with auto-implementations. You will often see stack traces, which are just an autoplay pool that pops an object, and without replication it is almost impossible to determine which object, which code path frees it, etc.

5) Sometimes, something as simple as refactoring can affect auto-implemented objects in ways that are not normally expected. The transition from simple iteration to block-based iteration is an autostart pool that can free an object before you can save it.

Usually the most appropriate use of auto-implemented objects is objects that are created "on the fly" and returned by the non-constructor method. Thus, the calling code has the ability to save the object, but the called method should not worry about the appointment of the owner.

It was a rather long exhaustion and perhaps beyond the scope of the original question, but I think it is important to know the β€œwhy” behind good decisions in memory management.

0
source

All Articles