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).
Related
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
I'm developing an iOS5 App using ARC, and I started to get some random EXEC_BAD_ACCESS crashes that I cannot figure out.. By random I mean it is very unpredictable: sometimes it may take a long time to crash, sometimes short. and there is also no one specific button/tablecell/etc. that trigger the crash. Every user interaction can possibly crash the app, but you cannot repeat the crash.
I have tried to turn on NSZombie and also some malloc debugger tools. In Instruments the crash error reads: An Objective-C message was sent to a deallocated object (zombie) at address: 0x10bd1b40. And the last part of the reference count log looks like this:
475 CoursesFirstViewController Release 2 02:23.253.631 0 UIKit -[UINibDecoder finishDecoding]
476 CoursesFirstViewController Release 1 02:23.253.838 0 Foundation -[NSAutoreleasePool drain]
477 CoursesFirstViewController Zombie -1 02:35.752.420 0 Foundation objectHash
The 2, 1, -1 thing are the reference counts. I have no idea why it skips 0 and drop to -1, crashing the program (all entries but the last have continuous ref counts). Also I have no idea what objectHash is.
My app comprises of multiple functions, accessible as icons on my main screen. CoursesFirstViewController is one of the functions. Always, it is CoursesFirstViewController and objectHash that crash the app, even if I am at somewhere else. (This is the case for the log above: I went out of CoursesFirstViewController (thus returning to the main screen of my app) at 02:23, but after 12 sec, when I was in some other function, the app crashed) I only need to enter CourseFirstViewController, mess around with it for a bit, and then go elsewhere to continue using the app, and after a while it will just crash.
I'm really mad of this problem now. I have searched SO and Google for quite a while but cannot find a solution. Any help will be greatly greatly appreciated. Thanks!!
#robmayoff yea I already checked that but didn't see anything especially useful there. the last few calls are objectHash, hashProbe, [NSConcreteHashTable rehashAround], [NSConcreteHashTable removeItem] etc.
This is actually somewhat useful. This is telling us that a collection, probably an NSDictionary, but possibly an NSSet is being destroyed. From your earlier information it seems to be an autoreleased collection that is created during the nib instantiation process (so probably an ivar of CoursesFirstViewController). That's where I'd be looking anyway given the symptoms, but the crash seems to confirm it.
General recommendations are auditing any __bridge casts or unsafe_unretained properties.
Another hunch is that you've named a method in a way that violates Cocoa memory management. The most likely misnaming would be that you have a property that starts with new or copy. This would definitely be an issue if you have ARC code call misnamed non-ARC code.
I suspect one of your properties is marked "weak" when it should be "strong" and is going out of scope and getting released before you access it. ARC can't save you in that case and you will get the above random crash behavior.
If you don't have any luck finding it I would resort to doing a global search for "weak" properties on your project and double-check each one to make sure it isn't something you expect to hang around. It's tedious but honestly doesn't take that long to do and sometimes turns up more than the one bug.
I gather from your Instruments output that the zombie object is of type CoursesFirstViewController. We often use a view controller as the delegate for some other object, and most objects that have delegates do not retain their delegates.
I am assuming that you aren't using any unsafe_unretained properties or variables, or any retain-type properties. So I assume that none of your objects is keeping a dangling reference to the CoursesFirstViewController zombie.
Since the system libraries have to work with non-ARC code, they do not use ARC's weak references. So if some system object has a CoursesFirstViewController as its delegate, and the CoursesFirstViewController is destroyed but the system object is not, then the system object is left with a dangling reference to the destroyed object.
So, check whether you're using the CoursesFirstViewController as the delegate for any system objects. If so, are you sure those objects don't outlive the CoursesFirstViewController?
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.
I'm trying to track down some bugs, and one of them is related to a memory leak. It's an object that I can tell that something still has a reference to, since Instruments still shows it as being alive, but Instruments does not register it as a leak.
Is there anyway to look at an instance of an object in Objective-C and see what other objects still have a reference to that object?
I would recommend using the Allocations/ObjectAllocations Instruments template and then in the top right corner type the class name of your object (in the Category field).
You can then see the allocations increasing as you suggest and by viewing the extended detail you can see where they were allocated.
All content below this point was added by the OP (joshbuhler)
In the screenshot below, change the filter to "Objects List", and then by clicking on the little arrow to the right of the object's address, the history of memory events (alloc/retain/release/dealloc) will be show for that object. It won't show you exactly what is hanging onto that object, but it will give you some very useful info for tracking it down.
Cautionary Tail: :)
In the process of searching for a memory leak, I set a breakpoint (really a logpoint) in Xcode that would log the value of self when it was triggered troublesome logpoint image. Meanwhile I found the leak and patched it, but the memory usage wasn't leveling out, and my de-init was never getting called. The logpoint I set earlier was actually causing the retain count of my object to increase, and in turn that prevented de-init from ever getting called. I happened to discover this after several hours of wild goose chases which culminated in me stepping through my object's methods line by line, issuing p CFGetRetainCount(self) from debug console. When I stepped over the line with the logpoint, the retain count went up. At first I assumed it was some strange side effect of my code. I moved that logpoint so that I could set a normal breakpoint on that line, and my problem moved with it. I disabled the logpoint and the leak was gone. Hopefully this can help someone else.
If you're using xCode you can use the Performance tools to find the memory leaks. That will give you a nice graph of ALL memory allocation and if they are released or leaked.
xcode -> run -> Start with Performance Tools -> Leaks.
Memory leak detection tools
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.