Objective C: What does allocation 'count' mean (using instruments) - objective-c

I ran my app using Instruments and found that one of my methods' [UICustomButton loadButton..]" count under allocation is always increasing (see screenshot below) -
The method in question is triggered whenever I scroll a tableview and when the cell is visible.
My questions are
1) What does the count actually mean? Is it normal for it to keep increasing?
2) Is the increasing count the reason why my scrolling becomes increasingly laggy?

The count in the instruments show the number of instances of a given class your application has created that are stil alive. So it is normal to increase up to the point where your application has created all the objects it needs to have, then it should remain more or less constant (more or less because you will be probably creating and releasing objects all the time).
If the count never stops increasing you probably leak objects - create and not release properly. This may lead to slow down (if you are creating performance expensive objects or have to work with all the instances which are getting more and more for example), it will definitely lead to crash after you've used more memory that your app is allowed to use.
Did you reuse cells in tableView? You should, otherwise you'll get this very effect: increasing instance count, increasing memory usage, slow scrolling and crash after the time.

Now as far as i have understood the concept of the count i will try to explain this, count refers to the number of ownership claims that you outstanding on a object and can be checked with the help of a function called as the -retainCount, but you should never pay any attention to the value of the retain count as its never correct and always confusing,
you don't know what's being retained, why it's being retained, who's retaining it, when it was retained, and so on.
For example:
You'd think that [NSNumber numberWithInt:1] would have a retainCount of 1. It doesn't. It's 2.
You'd think that #"Foo" would have a retainCount of 1. It doesn't. It's 1152921504606846975.
You'd think that [NSString stringWithString:#"Foo"] would have a retainCount of 1. It doesn't. Again, it's 1152921504606846975.
Basically, since anything can retain an object (and therefore alter its retainCount), and since you don't have the source to most of the code that runs an application, an object's retainCount is meaningless.
If you're trying to track down why an object isn't getting deallocated, use the Leaks tool in Instruments. If you're trying to track down why an object was deallocated too soon, use the Zombies tool in Instruments.
But don't use -retainCount. It's a truly worthless method.

Related

Object with reference count equals to 0 is still persistent

I am trying to enhance the memory allocation in my non-ARC app.
There are some objects that, even if their reference count are 0, they are listed as persistent object between two heapshot.
This is my heapshot view:
Lets take for instance the selected LSBookChapter in the 1st heapshot (0x6deb180).
This is the history of that object:
Why that object isn't deallocated? If the reference count is 0 I can't figure out when I over retained that object..
Might you have zombie detection turned on?
Zombie detection causes nothing to be deallocated, but -- likely -- the retain count will drop to zero and, more usefully, you'll see a one to one correspondence between retain causing and release causing events.
Also, if you don't turn on "only track live allocations", then you'll see the object in Instruments after it is deallocated, with a 0 retain count, but it is really deallocated.
In my previous application, I had some concerns as you are having right now because, I didn't had leaks, but the memory was growing. After some research I stumbled upon this. I did tried to make some shortcuts on his article, but in the end I just read the whole thing to actually understand what was wrong. And YES, I was able to pinpoint every problem I had. And I might say I had quite a few.
For your particular problem, I didn't do what you are you trying right now: seeing the retainCount of an object in different heapshots. I think it's a waste of time honestly. My main goal is to make sure that if I do something and I reverse it, the memory should not increase or if it does it should be slightly (quick example: going into a new UIViewController and press the button back).

Understanding Instruments and Memory Management

I'm in need of understanding how memory is managed in objective C.
I know the basics, if you create it and own it, you must release it yourself.
However, when it gets to code such as:
self.storeDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath2];
Do I own this? Must I release this memory?
self.storeDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath2];
//73.3% leak
totalCharacters = [storeDict count];
tagCounter = 1;
dictKeyArray = [[storeDict allKeys] mutableCopy];
//13.3% leak
When Instruments puts a bunch of percentages next to the highlighted leaks, what does that tell me? Does it tell me the size of the leak relative to the total amount of memory leaked?
And one last thing.. Is it normal for the amount of allocated memory to continuously rise? Or should it stabilize somewhere?
Thanks for all the help! Everything is greatly appreciated!
In most cases, you only own objects returned by methods whose names begin with "alloc", "new", "copy", or "mutableCopy". Of course, you also own anything to which you send -retain. Exceptions to these rules should be called out in the documentation for the non-conforming methods.
See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-SW1
Instruments attributes a leak to the line where the object was created. However, that's not necessarily the code which leaked the object. If the pointer to the object was passed to some other code and that code did not balance its retains and releases, then that code is responsible for the leak. Instruments can show you the history of retains and releases for a specific object, and you'll have to review those to see which code is not discharging its ownership responsibilities properly.
Also, if an object is owned by another object and it's really that second object that was leaked, then everything it owned will have leaked "transitively" as it were. So, look for higher-level objects which have leaked before trying to track down low-level objects which have leaked. Often, it is the objects which have leaked fewer instances which are the root of a graph of leaked objects.
Whether it is normal for memory to keep rising or to stabilize, that depends a little. Usually, memory usage should stabilize. However, if your app really is doing more and more, then it may be normal for its memory usage to keep increasing. For example, if an app is receiving data over the network and accumulating results as it does so, then its memory usage would likely rise as more data arrives. But if it doesn't stop at some reasonable point, that's a problem. On an iOS device, the system will eventually kill it.

Memory Leaks profiler in Xcode - How reliable is it?

I have tried using the memory profiler in xCode.
It flags a number of objects as leaked object but when I open the history of the object, the last operation on that object is a release that sets the object reference's count to zero.
How reliable is the results shown in that tool ? are they potential memory leaks or confirmed ones ?
And if it is definitely a memory leak why is it happening when I have the last reference count is zero ? could it be something wrong in the way I am configuring xCode's profiler (I just press cmd + i)?
Jamil
The allocations tool is perfectly accurate if you have asked it to track retains and releases: it tracks them correctly. It also reports correctly the difference between how many of an object have existed during the previous history and how many exist right now.
The leaks tool is not always accurate: for example, in my experience it often misses leaks (I've never heard of its reporting a false positive but I suppose it's possible). Remember to allow enough time, though, since by default the leaks tool only takes a shot every 10 seconds. Also, use heapshots to hone in on the lifetime of objects.
Ah I found the mistake !
I wasn't calling [super deallco] in the dealloc of the class of these instances

What do you think about this code in Objective-C that iterates through retain count and call release every iteration?

I'm still trying to understand this piece of code that I found in a project I'm working on where the guy that created it left the company before I could ask.
This is the code:
-(void)releaseMySelf{
for (int i=myRetainCount; i>1; i--) {
[self release];
}
[self autorelease];
}
As far as I know, in Objective-C memory management model, the first rule is that the object that allocates another object, is also responsible to release it in the future. That's the reason I don't understand the meaning of this code. Is there is any meaning?
The author is trying to work around not understand memory management. He assumes that an object has a retain count that is increased by each retain and so tries to decrease it by calling that number of releases. Probably he has not implemented the "is also responsible to release it in the future." part of your understanding.
However see many answers here e.g. here and here and here.
Read Apple's memory management concepts.
The first link includes a quote from Apple
The retainCount method does not account for any pending autorelease
messages sent to the receiver.
Important: This method is typically of no value in debugging memory
management issues. Because any number of framework objects may have
retained an object in order to hold references to it, while at the
same time autorelease pools may be holding any number of deferred
releases on an object, it is very unlikely that you can get useful
information from this method. To understand the fundamental rules of
memory management that you must abide by, read “Memory Management
Rules”. To diagnose memory management problems, use a suitable tool:
The LLVM/Clang Static analyzer can typically find memory management
problems even before you run your program. The Object Alloc instrument
in the Instruments application (see Instruments User Guide) can track
object allocation and destruction. Shark (see Shark User Guide) also
profiles memory allocations (amongst numerous other aspects of your
program).
Since all answers seem to misread myRetainCount as [self retainCount], let me offer a reason why this code could have been written: It could be that this code is somehow spawning threads or otherwise having clients register with it, and that myRetainCount is effectively the number of those clients, kept separately from the actual OS retain count. However, each of the clients might get its own ObjC-style retain as well.
So this function might be called in a case where a request is aborted, and could just dispose of all the clients at once, and afterwards perform all the releases. It's not a good design, but if that's how the code works, (and you didn't leave out an int myRetainCount = [self retainCount], or overrides of retain/release) at least it's not necessarily buggy.
It is, however, very likely a bad distribution of responsibilities or a kludgey and hackneyed attempt at avoiding retain circles without really improving anything.
This is a dirty hack to force a memory release: if the rest of your program is written correctly, you never need to do anything like this. Normally, your retains and releases are in balance, so you never need to look at the retain count. What this piece of code says is "I don't know who retained me and forgot to release, I just want my memory to get released; I don't care that the others references would be dangling from now on". This is not going to compile with ARC (oddly enough, switching to ARC may just fix the error the author was trying to work around).
The meaning of the code is to force the object to deallocate right now, no matter what the future consequences may be. (And there will be consequences!)
The code is fatally flawed because it doesn't account for the fact that someone else actually "owns" that object. In other words, something "alloced" that object, and any number of other things may have "retained" that object (maybe a data structure like NSArray, maybe an autorelease pool, maybe some code on the stackframe that just does a "retain"); all those things share ownership in this object. If the object commits suicide (which is what releaseMySelf does), these "owners" suddenly point to bad memory, and this will lead to unexpected behavior.
Hopefully code written like this will just crash. Perhaps the original author avoided these crashes by leaking memory elsewhere.

Code Example: Why can I still access this NSString object after I've released it?

I was just writing some exploratory code to solidify my understanding of Objective-C and I came across this example that I don't quite get. I define this method and run the code:
- (NSString *)stringMethod
{
NSString *stringPointer = [[NSString alloc] initWithFormat:#"string inside stringPointer"];
[stringPointer release];
[stringPointer release];
NSLog(#"retain count of stringPointer is %i", [stringPointer retainCount]);
return stringPointer;
}
After running the code and calling this method, I notice a few things:
Normally, if I try to access something that's supposedly dealloced after hitting zero retain count, I get a EXC_BAD_ACCESS error. Here, I get a malloc "double free" error instead. Why is that?
No matter how many lines of "[stringPointer release]" I add to the code, NSLog reports a retain count of 1. When I add more releases I just get more "double free" errors. Why aren't the release statements working as expected?
Although I've over-released stringPointer and I've received a bunch of "double free" errors, the return value still works as if nothing happened (I have another NSLog in the main code that reports the return value). The program continues to run normally. Again, can someone explain why this happens?
These examples are fairly trivial, but I'm trying to get a full grasp of what's going on. Thanks!
You're getting a double free error because you are releasing twice and causing two dealloc messages. =P
Keep in mind that just because you release doesn't doesn't mean the data at its memory address is immediately destroyed. It's just being marked as unused so the kernel knows that, at some point in the future, it is free to be used for another piece of data. Until that point (which is totally nondeterministic in your app space), the data will remain there.
So again: releasing (and dealloc'ing) doesn't necessitate immediate data destruction on the byte level. It's just a marker for the kernel.
There are a couple of things going on here. First, deallocing an object doesn't necessarily clear any of the memory the object formerly occupied. It just marks it as free. Unless you do something else that causes that memory to be re-used, the old data will just hang around.
In the specific case of NSString, it's a class cluster, which means that the actual class you get back from alloc/init is some concrete subclass of NSString, not an NSString instance. For "constant" strings, this is an extremely light-weight structure that just maintains a pointer to the C-string constant. No matter how many copies of that striing you make, or how many times you release it, you won't affect the validity of the pointer to the constant C string.
Try examining [stringPointer class] in this case, as well as in the case of a mutable string, or a formatted string that actually uses a format character and arguments. Probably all three will turn out to have different classes.
The retainCount always printing one is probably caused by optimization - when release notices that its going to be deallocated, there's no reason to update the retainCount to zero (as at this point nobody should have a reference to the object) and instead of updating the retainCount just deallocates it.