Why did this code crash into an iOS application with "Out Of Memory"?

My question originally concerned a line loaded from disk, and my application went out of memory, but there was a much simpler way to make this crash, and I don't understand why. Run the code below and it will die in a few seconds (iPad 4.2). Theoretically, he should just run forever. No links are stored in the large StringBuilder, and it is immediately set to NULL. If I look at it in the Tools, the memory can take up to 160 MB after several cycles, and the application will die. Why is the memory not released? Each cycle increases memory by about 10 MB ...

One thought is that the GC just can't keep up, but no matter how long the delay in Thread.Sleep () is, the memory will eventually disappear.

The test may look academic, but I have a problem with a real application that is crashing. It has a method that returns a (huge) string from a WebService request, converts that string into an XmlDocument and parses it (saves something in the database). Then the method exits, but the memory remains high. If I repeat the same method again (after an hour or so!), The application dies OOM. Why is memory still allocated?

public override bool FinishedLaunching ( UIApplication app, NSDictionary options ) { Thread oThread = new Thread ( DoIt ); oThread.Start ( ); return true; } public void DoIt () { using(var o = new NSAutoreleasePool()) { while(true) { StringBuilder oSB = new StringBuilder(); for(int i = 0; i < 800000; ++i) { oSB.Append("1234567890"); } oSB = null; Thread.Sleep(1000); } } } 

EDIT . I noticed that if I change the Do () method as shown below, the memory will remain stable. He rises for a while, then the GC bursts in and clears it. If I add s.Dispose () after creating an NSString, the memory will not go up at all. So this is a problem with .NET string classes.

 public void DoIt () { using(var o = new NSAutoreleasePool()) { StringBuilder oSB = new StringBuilder(); for(int i = 0; i < 800000; ++i) { oSB.Append("1234567890"); } while(true) { NSString s = new NSString(oSB.ToString()); Thread.Sleep(1000); } } } 
+4
source share
2 answers

StringBuilder internally allocates new large arrays at each iteration (size can be doubled). In the end, you get a fragmented heap.

+1
source

perhaps the text is uncompressed in memory

0
source

Source: https://habr.com/ru/post/1339734/


All Articles