App Crashes saying Memory Warning Using Arc [close

2020-03-04 08:55发布

问题:


Want to improve this question? Update the question so it's on-topic for Stack Overflow.

Closed 6 years ago.

I am using ARC and the app crashes saying received memory warning. I have used the apple instruments:

It looks like I do not have any leaks but I cannot find where is wrong. The crash has to do with the memory and due arc I cannot use release and any sort. It is my first time dealing with memory usage using arc. Is there away I can Debug this since I am dealing this for nearly two months. I have my code on my git hub so it will be helpful if you look at it. You can find it here.

I am dealing this problem for weeks and want to end this. Thanks.

回答1:

Not all "leaks" show up in the "Leaks" tool in Instruments. And, notably, if a view controller has a strong reference cycle, not only will the view controller not be deallocated, but none of its members will be deallocated either. But looking at your allocations your memory is never getting released, so you probably do have a leak somewhere. It's hard for us to diagnose, though, because your github project is incomplete. But here are a few thoughts:

  1. Strong reference cycles don't always show up in the Leaks tool.

  2. In a variation of the traditional strong reference cycle, your code employs a repeating NSTimer that will keep a strong reference to your view controller which will result in your view controller never being released (because the timer maintains its own strong reference to your view controller). To fix this, your view controller must stop the timer when the associated view disappears:

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    
        self.timer = [NSTimer scheduledTimerWithTimeInterval: 0.05f target: self selector: @selector(tick) userInfo: nil repeats: YES];
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
    
        [self.timer invalidate];
        self.timer = nil;
    }
    
  3. Besides of strong reference cycles, like above, another phenomenon that can result in increasing allocations like you've shared with us is a circular flow between view controllers. For example, if your app does a push/modal segue from view controller A to view controller B, the app must then pop/dismiss/unwind back to view controller A. If you push/modal from B to a new instance of A, you'll end up abandoning your old instance of A, resulting in an allocations graph like yours.

These are just a few examples of the sorts of things that can result in your allocations graph. But it's hard for us to diagnose further with the limited information provided.

Before doing anything else, use Xcode's static analyzer (command+shift+B or "Analyze" on the "Product" menu) and make sure you get a clean bill of health there. Let Xcode help you identify your programming issues in your code.

Once you've resolved any issues identified by the static analyzer, you can then dive into Instruments. Refer to the WWDC 2012 video, iOS App Performance: Memory. About 32 minutes into it, it shows an allocation graph much like yours, describes the three sources of those sorts of issues (leaks, abandoned memory, or cached memory), and shows you how to use the Allocations tool to identify the precise source of the problem.

You should follow along that video and you'll definitely gain some familiarity with Allocations tool features (such as comparing heap snapshots) to identify what object leaked, or look at the extended details and call tree to find the source code that created the leaked object. Once you identify precisely what's leaking, we can help you resolve the issue.


By the way, even easier than the heapshots described in that video, I'll often just option-click-and-drag at a particular spike (notably one that obviously is never released) in the graph in "Allocations". If you do that, the object summary will show you the objects (most useful if you sort by "Live Bytes") that have been allocated and not released during that window of execution:

That can be helpful, but sometimes it's just cryptic CFString or CGImage allocations. It's therefore sometimes useful to see where in your code those objects were allocated. If you switch from "Statistics" - "Object Summary" to "Call tree", it will now show you how much memory was taken up by each of your methods (and I find this screen most useful if I also check "Invert Call Tree" and "Hide System Libraries"):

If you then double click on a symbol name here, it will actually show you the offending code:

Through that process, I can see what is being allocated at that spike, and I can now go about identifying why that memory is never getting released (in this case, it was my deliberate use of a repeating timer that I never invalidated).

There are other tricks that are useful in more complicated scenarios (I'm particularly fond of having my code signaling flags that appear in instruments so I can more accurately correlate activities in my code with what's going on in Instruments), but that's probably too much to get into here. Hopefully this option-click-and-drag in Instruments will be a useful tool to identify what's being allocated and never released.



回答2:

  1. There are cases where ARC doesn't work (by design, I mean). When you use CoreFoundation or anything else below the Cocoa level you need to manage your memory as before. Also, you could have retain cycles (most often with blocks). Try analyzing the project (next to Build in Xcode) or running with Instruments
  2. ARC doesn't help if you're just using a lot of memory. It's possible your data set is just too large and you need to refactor to use less memory at a given time


回答3:

As I have glance you code on github

  1. There is one file name iCarousel.m.make sure it is ARC compatible and if not than go to the Target/Build phases/complie sources and give fno-objc-arc flag to iCarousel.m.

  2. Make all objects nil in viewdidunload method of all classes.

hope it will help you.