I am having few issues on iPad app, related to CoreData.
This time regarding deleting of object.
Looking at instruments (allocation template) I found that my deleted object stays in memory forever, or at least 7hours, the time I left instruments on. Also the leak instruments doesn't show anything about.
I double check, after saving the context, both the table view which is not displaying the object among its row, and the database itself, that has physically a missing row.
I am not able, with instruments, to tell who is keeping a reference to it, preventing the object to be deallocated.
I am using ARC, and an NSFetchedResultsController is managing the UITableView.
Do you have any guess, or suggestion about what instruments to use.
You shouldn't worry about that. If you try to access the object, core data will give you an exception telling you it couldn't fulfill a fault for that object. The object is gone from your application's database. Core data's internal work might keep a reference to it for other purposes, but that purpose is out of your control.
Related
I try to authenticate my app with Twitter with following code: pastebin
However, if I remove the (useless?) loop line 23ff
for (ACAccount *acc in arrayOfAccounts) {
[acc accountType].identifier;
//Otherwise the identifier get lost - god knows why -__-
}
the acc.type becomes (null) when it gets executed further in
AccountHandler checkAccountOf:acc. If I leave the loop in, the type is correctly set.
I am pretty sure it has to do with the fact that I am in a block and then move on to the main queue, but I am wondering if I am doing something wrong? This loop does not look like sth I am supposed to have to do.
Something kinda similar happened here.
ACAccounts are not thread safe. You should use them only on the thread that they originate. And for this purpose you can read 'thread' as 'queue'.
While I've not seen formal documentation of that, if you NSLog an account you'll see that it's a Core Data object and the lack of thread safety on Core Data objects is well documented.
The specific behaviour is that a Core Data object can be a fault. That means that what you're holding is a reference to the object but not the actual object. When you try to access a property the object will be loaded into memory.
What Core Data is doing underneath is caching things in memory and returning faults until it knows that an object is really needed. The efficient coordination of that cache is what limits individual instances of the Core Data object that coordinates objects to a single thread.
If you do the action that should bring the object into memory on the wrong thread — which is what happens when you access identifier here — then the behaviour is undefined. You could just get a nil result or you could crash your application.
(aside: the reason that Core Data works like this is that it stores an object graph, so possibly 1000s of interconnected objects, and you can traverse it just like any other group of objects. However you don't normally want to pay the costs associated with loading every single one of them into memory just to access whatever usually tiny subset of information you're going to use, so it needs a way of providing a normal Objective-C interface while lazily loading)
The code you've linked to skirts around that issue by ensuring that the objects are in the cache, and hence in memory, before queue hopping. So the 'fetch from store' step occurs on the correct queue. However the code is nevertheless entirely unsafe because objects may transition from being in memory back to being faults according to whatever logic Core Data cares to apply.
The author obviously thinks they've found some bug on Apple's part. They haven't, they've merely decided to assume something is thread safe when it isn't and have then found a way of relying on undefined behaviour that happened to work in their tests.
Moral of the story: keep the accounts themselves on a single thread. If you want to do some processing with the properties of an account then collect the relevant properties themselves as fundamental Foundation objects and post those off.
this a question I always wanted to ask.
When I am running an iOS application in Profiler looking for allocation issues, I found out that NSManagedObject stays in memory long after they have been used and displayed, and the UIViewController who recall has been deallocated. Of course when the UIViewController is allocated again, the number is not increasing, suggesting that there's no leak, and there's some kind of object reuse by CoreData.
If I have a MyManagedObject class which has been given 'mobjc' as name, then in profiler I can see an increasing number of:
MyManagedObject_mobjc_
the number may vary, and for small amount of data, for example 100 objects in sqllite, it grows to that limit and stays there.
But it also seems that sometimes during the application lifecycle the objects are deallocated, so I suppose that CoreData itself is doing some kind of memory optimizations.
It also seems that not the whole object is retained, but rather the 'fault' of it (please forgive my english :-) ) because of the small live byte size.
Even tough a lot of fault objects would also occupy memory.
But at this point I would like some confirmation:
is CoreData really managing and optimizing object in memory ?
is there anything I can do for helping my application to retain less object as possible ?
related to the point above, do I really need to take care of this issue or not ?
do you have some link, possibly by Apple, where this specific subject is explained ?
maybe it is relevant, the app I used for testing rely on ARC and iOS 5.1.
thanks
In this SO topic, Core Data Memory Management, you can find the info you are looking for.
This, instead, is the link to Apple doc on Core Data Memory Managament.
Few tips here.
First, when you deal with Core Data you deal with an object graph. To reduce memory consumption (to prune your graph) you can do a reset on the context you are using or turn objects into fauts passing NO to refreshObject:(NSManagedObject *)object mergeChanges:(BOOL)flag method. If you pass NO to that method, you can lose unsaved changes, so pay attention to it.
Furthermore, don't use Undo Management if you don't need it. It increases memory use (by default in iOS, no undo manager is created).
Hope that helps.
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).
I'm really pulling my hair out on this one, it seems that I'm having severe issues with memory management on an iOS app.
Here's the case: first I load table. When the user taps a cell, it presents a complicated view. The most memory consuming about the view is that it's loading 20+ UIImages of 500x500. There are two other tabs in that view, loading a list of media (those UIImages, but then in a table) and another simple table.
When I return back to the first table view, apparently over 250 kB is still allocated on heap. I know the view is complicated, but there's no reason to keep so much memory alive. And well, guess what, when I do switch to the view a lot, eventually the app runs out of memory and gets killed.
What I tried to solve it:
Fix all Analyze issues, so according to that there are no leaks anymore.
Check all inits again for releasing, making use of autorelease where possible.
Checking all the memory leaks using Instruments -> Leaks. In a runtime of 6, I get not more than 2 or 3 leaks.
Last, Instruments -> Allocation, checking the heap. This is what bothers me, between two marked heapshots I get a difference of 250+ kB. I've looked into it, using the detailed views. I can't get my head around it: when it's pointing to one of my methods/classes, I'm pretty sure everything in there is either released or autoreleased. It's also pointing to a lot of not-mine (say QuartzCore) methods/classes.
Also, I don't understand why autorelease is not autoreleasing. I mean, it sometimes looks like an object that is marked for autoreleasing, is released way too late. I haven't created any NSAutoreleasePools myself, so is it possible that the pool is drained only when the runtime stops? How can I periodically drain the pool (even if it's not mine).
Any help is greatly appreciated.
Kind regards,
Reinder
Used this for the heap checking: http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/
Are you using imageNamed to load your images - this method will keep all images cached in memory. Try initWithContentsOfFile instead.
Watch out though; initWithContentsOfFile: won't cache at all so if you use this method a lot for the same image then you should be using imageNamed:!
I think you might want to try to optimize your design first and read guides for efficent memory management. A better understaning of the components and the runtime helps more than tracking memory allocations and will make it easier to find the leaks.
First you should always use release. Only use autorelease when necessary.
Make sure you follow the guidelines for UITableView implementations and efficient management of UITableViewCells (lazy loading, cell reusing etc.).
Check if you have retain-cycles (retained view controllers won't be deallocated).
Track the deallocation of your view controllers and objects
Don't keep stuff in memory you don't need anymore.
Don't load stuff you don't need right now.
I think there is something I'm missing about memory management. Here's the code:
NSString *string = #"foo";
[string release];
NSLog(#"%#", string);
I expect to get a memory error with that code, but instead the code is ran without errors. I noticed this as I was following a book and a scrollView was released before setting properties and adding a subView (but after being inserted in the main view).
My question is, when are objects really deallocated? Would this e considered good coding style?
This works because your string variable is pointing to a constant string that has been compiled into your application. retaining it does nothing and releaseing it does nothing as well. It exists in static memory, and it will only be destroyed when your program is unloaded from memory.
If you alloc, retain or copy an object, it is your responsibility to release it. Everything else is dealt with by the system and will be flushed with the auto release pool.
There are way too many memory management questions on SO already, have a quick look around to get yourself acquainted https://stackoverflow.com/search?q=memory+management+iphone
[edit]
Probably the most important part of your question that you need to understand is in your second last paragraph:
I was following a book and a scrollView was released before setting properties and adding a subView (but after being inserted in the main view).
I haven't seen this code but it is likely that you added the scrollView to your UIView instance. In these cases, the receiving view always retain its subview(s) so you are free to release it.
Once the UIView instance is released it wil also send a release message to all its subviews, which includes the scrollView.
Makes sense?
Sending a message to a deallocated object is undefined behavior. You might get a memory error, you might end up sending a message to another object, you might end up sending an message to a phantom version of the former object — it all depends on implementation details and details of the environment at runtime that are mostly out of your control. In this specific case, you're running into the implementation detail that NSString constants are immortal.
As for specifically when an object will be deallocated, that's also an implementation detail. If you don't own an object and don't have a reasonable guarantee that it will still be around (e.g. you just got it by doing [someArrayYouOwn objectAtIndex:0]), you should not be dealing with it.
The best policy: Just don't send messages to objects you no longer own. Follow the memory management rules.