I just started working on a relatively complex project, and have discovered a bug. When the user logs out, the view controllers are still allocated behind the login view controller. They continue responding to rotation events, etc. I have set the controller to nil upon logout, but it's still responding, which indicates that some other object still has a pointer to it. (This project has ARC enabled.)
Pre-ARC I could likely solve this by overriding retain:
- (id) retain
{
// Break here to see who is retaining me.
return [super retain];
}
How can I use the Xcode debugging tools to select an object and list all the other objects that point to it? Is there a better approach than simply hunting through all the code?
As of Xcode 8 you can use the Debug Memory Graph:
Run your app and look at the navigator at the bottom of the screen. You should see a set of three connected circles:
Navigate to wherever so that your object is allocated in memory and then tap on this icon. It should pause your app and a graph should pop up on your Xcode screen. Now, on the left side of the screen you can see a list of objects. Find the object you want to see all the pointers to and click on it. Now they should be visible in the graph. You can expand these branches by tapping on the two arrows on the nodes at the left end of the branch. The graph should look something like this:
This saved me literally days of work. It's an extremely useful tool. I hope it helps someone else too.
The Instruments Heapshot Analysis tool was the best thing I could find for this purpose. This article provides a more complete tutorial, but the basic steps are:
Select Product -> Profile. Choose the Allocations Instrument.
On the left, press the Mark Heap button before/after significant events. In my case, this was before login, after login, and after logout.
Search through the Heapshot for the class you're looking for.
Press the disclosure triangle to see its memory address(es).
Press the arrow to the right of a memory address to see its responsible caller (it appears in the rightmost column.)
If someone else writes up a more thorough explanation, or can offer any related lldb commands, I'm happy to mark your answer as correct.
Related
I want to be explicit that I am not referring to the quick look feature built into XCode:
My issue with this approach is that I need to review about 50 images per run, and the action of clicking through each time is going to give me carpal tunnel at this point.
I do not think there is something officially baked into XCode that will provide what I want, so my hope is that there is a third party tool that can handle this. Preferably, something that may place it in the variable in the debug console so that I may view the image.
Not exactly what I was looking for, but something that XCode does provide is fairly close to what I want.
When a breakpoint is hit, select the variable in the console
Click on the eye icon seen below
The image window seen here will appear with an anchor to the variable
This is with XCode 8.
The benefit of this approach is that it saves me from having to track to the variable in code, hover over it, and then move the cursor just so such that the window does not close before I can click on the inspection icon.
I am having problem on memory leak tracking, i did try profiling but the instrument shows firapb_decode_repeated_user_attribute as as responsible object. And while i try to track code it takes me to assembly code which is more painful. Do anybody have similar issue or have some clue to track this issue, It will be a lot for me.
Leaked Object # Address Size Responsible Library Responsible Frame Malloc 32 Bytes 1 0x600000231ba0 32 Bytes appName firapb_decode_repeated_user_attribute
The Assembly code
Yes as Larme said it was the Firebase leaking the memory.
I am still not knowing the exact cause (line of code) but disabling firebase app analytics from firebase plist solved the problem,
Even you are not using firebase app analytics with setting IS_ANALYTICS_ENABLED = NO on GoogleService-Info.plist. fire base SDK seem executing the app analytic codes by default.
Solution:- Adding FIREBASE_ANALYTICS_COLLECTION_ENABLED = NO on GoogleService-Info.plist, wipe out the leak problem.
This is only my perception and observation, this topic may need more information and expiations.
If you want to find the area of your code where the leak occurs, switch to the call tree view. The jump bar is at the top of your first screenshot. Click the Leaks item in the jump bar and choose Call Tree to switch to the call tree view.
When you're in the call tree view, selecting the Invert Call Tree and Hide System Libraries checkboxes will make it easier to find your code in the call tree view. Starting with Xcode 8.3, the checkboxes are in a popover that you open by clicking the Call Tree button at the bottom of the window.
Earlier Instruments versions have a display settings section with a Call Tree collection of checkboxes.
So, I haven't been able to figure this out yet, because when I pause execution... Xcode doesn't really show what's going on:
This freeze happens when I scroll a very long UITableView around in the center of its scrollable area constantly, so that it's constantly reusing cells. I think that perhaps there is something not being retained for a dispatch block that might happen there, but I'm not yet sure since no data is displayed using the standard debugger and its a fairly complex view. (reference: https://stackoverflow.com/a/23501382/963901 )
I'm going to attempt some manual diagnosis here, but is there any other way of approaching this with Instruments or something, perhaps?
To investigate this sort of problem I'd suggest the following:
Disable the setting in Xcode's debug navigator pane that hides intermediate stack frames from you. It's one of the buttons at the bottom right of the pane that shows the stack trace.
Look at the newly-revealed portion of the backtrace to see what code is blocking on the semaphore.
Look at the other threads in your program to see which appear to be doing work related to the code discovered in step 2.
Long story here, so bear with me...
I have a view controller which, when presented more than three times throughout the life of an application session, will hang and lock and freeze my entire application. Even the Springboard locks up until my app's fully backgrounded! In Xcode's inspector, I noticed rather alarmingly that the memory footprint would jump a good 5-8 MB every time I presented that view, and it wouldn't go down again after dismissal. By the time the fourth invocation rolls around, the app's already using 40 MB of memory.
My first thought was, "OMG, itz a memry leek!" The second one told me to hop into Instruments and track it down.
While the Leaks tool did help some, it only told me that the app was leaking like crazy. All it would tell me was that, somewhere in these four second intervals, I had gained between "4 new leaks" and "17 new leaks." They did correspond to my opening that view, though, and once I started commenting random stuff (and following the sometimes helpful guidance of the Allocations tool), I tracked most of them down to three extra lines of code. "Oh well, I don't need those views anyway!" Those three lines no longer exist, and Instruments no longer complains.
My only complaint here is that my UI still behaves the same! On the fourth presentation, the entire app slows down. Upon further inspection of Xcode's instruments, I see that not only is the memory still going up (only to 30 rather than 40 MB this time), but the CPU activity has tanked!
Ok, granted I should have looked there in the first place, but I ain't perfect!
I ran the app again, and found that the overall CPU activity rose consistently the more I presented that view controller. By the third one, it was up to 40-60%. The main thread seemed pretty clear, and most of the activity was spread between eight other background threads (who knows what all those do).
The fourth time I opened that view, I had expected everything to block like crazy. It didn't. The CPU just... stopped. It was running at around 50-ish% when, by the time my finger had left the screen, it was down at 1%. All of the thread graphs shrunk from spiked stalagmites to tiny waves in a puddle. According to the pie chart, the vast majority of the processor was free to do as it liked. It doesn't like me.
I literally have no clue why it does this. I've been stuck in a room for days now trying to figure this out. Any help or advice would be much appreciated.
Does anyone have any idea why this happens, how this happens, or what I can do to make this not happen?? I'm drawing a blank here...
Thank you so much!
It should be noted that I got these by running the app on my iPhone 5s. Yes, I did try on the simulator, but my little MacBook Air took it like a champ, and was no help in figuring this out, except to tell me that the problem happened on iPhones.
I've run into this before, and the following is my general approach that usually allows me to fix these types of memory leaks.
First I would put a print statement into you viewController to see if your VC is being deallocated when it is being popped.
deinit {
print(self.description)
}
The next step, in the case that the ViewController is not being deallocated, I would start by removing core pieces, bottom up, commenting them out chunks one step at a time, yet leaving the back control that hides the view controller visible. Usually you can isolate the memory leak once you see the deInit get called after removing some code, you may have hit the part that made a strong cycle reference.
One more thing, ensure that all your delegates are declared weak, and search through your code for closures, and check that the closures aren't holding hard references within, especially to self.
Also, checkout this article to see the about using unowned or weak, when passing in instances into a closure, could be helpful.
http://krakendev.io/blog/weak-and-unowned-references-in-swift
I just started learning the instruments tool, and I'm pretty sure what I am seeing is not good. When I look at allocations, specifically the column "Live Bytes" and "Overall Bytes", I see the number continually increases as the app runs...
My app has two view controllers. A table view, and the second view controller displays detailed information about the row they selected in the table view, downloaded from the internet.
I kept clicking a row in the table view, followed by clicking the back button in the navigation bar... and LiveBytes continued to increase.
I'm guessing this means that my objects aren't being released from memory... but please correct me if I'm wrong.
MY QUESTION IS: How do I use the data in instruments/allocations to track down this memory issue? How do I find the objects not being released from memory?
I'm looking for tips on how to use these tools to clean up any memory problems my app has.
Thanks!
XCODE 4.2.1, deploying to iOS 5.0+
EDIT: I'm looking at the #living column and seeing objects like UIScrollView continuously increase... and never decrease. When I click the back button in a navigation bar, are objects automatically released from memory? When are objects released, or do I need to do it manually? Or could I be running into an issue due to using strong pointers, causing objects to not be released?
Whenever you want to observe memory usage in a cyclic pattern, there's the wonderful Heapshot analysis in the "Allocations" instrument.
Start your app and go to a default state.
In Instruments, press the "Mark Heap" button to create the "Baseline".
Do something in your app like pushing a view controller.
Return to the default state.
Press the "Mark Heap" button again to create a heapshot.
Repeat about five times from step 3.
This will result in a list of heapshots, each showing the objects that are still alive from that cycle. If your app has no leaks there will be no objects left in the middle heapshots.
The first one or two cycles might have warmed up some caches, the last two might not have cleaned up some reused resources. That's why it's usually a good idea to make four to six heapshots.
The magic in the heapshot analysis lies in the fact that the heapshots show you the leaked objects from previous cycles and remove them automatically when the objects are released later. In contrary to the "Leaks" instrument it also finds abandoned memory, not only leaks.
Most Probably you have discarded the arm64 and are running your app with armv7 only. Add both arm64 and armv7 as architectures
I think one of the best ways to solve memory issues is to use ARC.
Edit -> Refactor -> Upgrade to Objective-C ARC.
ARC will handle the majority of memory management in your app. Especially sice your app doesn't sound too complex, it might totally eliminate your problem. You still need to watch out for retain cycles and listen to memory warnings though. If you don't want to use ARC (which you should) at least run the static analyzer. Your problem might be something simple that the static analyzer can show you how to fix.
Edit:
You mentioned scroll views- this might be your problem: Memory leak every time UIScrollView is released
The profile tool has an instrument called 'Leaks'. It is similar to the 'Allocations' instrument but it shows you the object that was not released. May be you can use the 'Leaks' tool to find what is the object that was retained and release these object.