I have an iOS app written in Swift that is leaking memory - in certain situation some objects should be released but they are not. I have learnt about the issue by simply adding deinit
debug messages like this:
deinit { println("DEINIT: KeysProvider released") }
So, the deinit message should be present in console after such events that should cause the object to release. However, for some of the objects that should be released, the message is missing. Still, Leaks Developer Tool does not show any leaks. How do I solve such situation?
When analyzing possible memory leaks, you need access to the app's memory heap. Then you can analyze the memory contents. Looking at relationships between objects, you create theories on why memory isn't being freed. A common diagnostics data source is a memory dump on Windows or the equivalent core dump on Linux.
One way to check for memory leak is to press and hold down your Windows key and tap the Pause/Break key to bring up System Properties. Click on the Performance tab and check System Resources for the percentage of free or available RAM.
In Xcode 8, you can click on the "Debug Memory Graph" button, in the debug toolbar (shown at the bottom of the screen):
Just identify the object in the left panel that you think should have been deallocated, and it will show you the object graph (shown in the main canvas, above). This is very useful in quickly identifying where the strong references were established on the object in question. From here, you can start your research, diagnosing why those strong references were not resolved (e.g. if the object in question has a strong reference from something else that should have been deallocated, look at that object's graph, too, and you may find the issue (e.g. strong reference cycles, repeating timers, etc.).
Notice, that in the right panel, I'm seeing the call tree. I got that by turning on the "malloc stack" logging option in the scheme settings:
Anyway, having done that, one can then click on the arrow next to the relevant method call shown in the stack trace in the right panel of the first screen snapshot above, and you can see where that strong reference was originally established:
The traditional Instruments technique (especially useful if using older versions of Xcode) is described below, in my original answer.
I would suggest using Instruments' "Allocations" tool with the "Record Reference Counts" feature:
You can then run the app in Instruments and then search for your class that you know is leaking and drill in by clicking on the arrow:
You can then drill into the details and look at the stack trace using the "Extended Details" panel on the right:
In that "Extended Details" panel, focus on your code in black rather than the system calls in gray. Anyway, from the "Extended Details" panel, you can then drill into your source code, right in Instruments::
For more information and demonstrations in using Instruments to track down memory problems, please refer to:
Use instruments to check for leaks and memory loss due to retained but not leaked memory. The latter is unused memory that is still pointed to. Use Mark Generation (Heapshot) in the Allocations instrument on Instruments.
For HowTo use Heapshot to find memory creap, see: bbum blog
Basically the method is to run Instruments allocate tool, take a heapshot, run an iteration of your code and take another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.
To figure out the results disclose to see the individual allocations.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on (For Xcode 5 and lower you have to stop recording to set the option). Cause the app to run, stop recording, drill down and you will be able to see where all retains, releases and autoreleases occurred.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With