Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between abandoned memory and a memory leak?

Both are exactly the same thing, except that "abandoned memory" refers to a whole object graph leaked rather than just a single object. Right?

like image 389
openfrog Avatar asked Jan 12 '12 18:01

openfrog


People also ask

What are memory leaks?

DEFINITION A memory leak is the gradual deterioration of system performance that occurs over time as the result of the fragmentation of a computer's RAM due to poorly designed or programmed applications that fail to free up memory segments when they are no longer needed.

Can memory leaks damage RAM?

Memory leaks don't result in physical or permanent damage. Since it's a software issue, it will slow down the applications or even your whole system. However, a program taking up a lot of RAM space doesn't always mean its memory is leaking somewhere. The program you're using may really need that much space.

What is the main cause of memory leaks?

Following are the main reason of memory leak. Holding references to managed objects (classic case of event handler not released.) I have noticed timer also causes the memory leak. Do dispose it if you are using any of the timer.


1 Answers

First, you need to understand the notion of a "memory object graph" or "application object graph" (or, simply, "object graph" as it applies to allocated buffers). In this case, "object" refers to any allocation in your application, be it an object or a simple malloc()ed buffer. The "graph" part if it is that any object can contain a reference to -- a pointer -- to other objects.

The "live object graph" of an application are all of the allocations that can be reached, directly or indirectly, from the various "roots" in the application. A "root" is something that, on its own, represents a live reference to an object, regardless of whether or not anything else explicitly references the root.

For example, global variables are roots; by referring to an object, a global variable, by definition, makes that object part of the app's live object graph. And, by implication, any objects that the object referred to by the global variable are also considered to be live; not leaked.

The same goes for the stack; any object referred to by any thread's live stack is, itself, considered live.

With this in mind, a leak and abandoned memory actually do have two distinct meanings.

Leak

A leak is a piece of memory for which there are no references to the allocation from any live object in the application's live object graph.

I.e. the memory is unreachable and, thus, there is no way that it can ever be referred to again (barring bugs). It is dead memory.

Note that if object A points to object B and object B points to A, but nothing in the live object graph points to either A or B, it is still a leak. If the B->A and A->B references are both retained references, you got yourself a retain cycle & a leak.

Abandoned Memory

Allocations that are in the app's live object graph but are no longer reachable due to application logic issues are considered abandoned, but not leaked.

For example, say you have a cache whose entries are instances of NSData that were downloaded from some URL where the URL contains a session ID in the URL (a common pattern) and that session ID + URL are used as the key to look up stuff in the cache. Now, say the user logs out, causing the session ID to be destroyed. If the cache isn't also pruned of all entries specific to that session ID, then all of those NSData objects will be abandoned, but not leaked as they can still be reached via the cache.


In reality, there is little use in making this strong of a distinction between the two save for that fixing either requires very different strategies.

Fixing a leak is to figure out where the extra retain came from (or where a missing call to free() might need to be inserted, in the case of a malloc() based leak). Since a detected leak cannot be reached from the live object graph, fixing a leak is really this straightforward.

Fixing abandoned memory can be considerably trickier for a couple of reasons.

First, the memory is still reachable from the live object graph. Thus, by definition, there is an algorithmic problem in your application that is keeping the memory alive. Finding and fixing that can often be much more difficult and potentially disruptive then fixing a mere leak.

Secondly, there might be non-zeroing non-retained weak references to the abandoned allocation. That is, if you figure out where to prune the strong references and make the allocation actually go away, that doesn't mean that your work is done; if there are any remaining non-zeroing weak references, they will now be dangling pointers and..... BOOM.


As Amit indicated, Heapshot Analysis is quite adept at finding both leaks, abandoned memory and -- quite important -- overall "Undesirable Memory Growth".

like image 170
bbum Avatar answered Sep 27 '22 21:09

bbum