I have the following code in a loop iterating over the different document objects:
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSData* data = [document primitiveValueForKey:#"data"];
[document.managedObjectContext refreshObject:document mergeChanges:NO];
[pool release];
The "data" property is a large blob (a 1MB image).
And as I monitor the memory with the Allocation Instrument memory usage is increasing. I cannot find where the leak is coming from and how to remove it.
Thanks!
Something is wrong with your sample code, did you mean:
NSData *data = [document primitiveValueForKey:#"data"];
As data is currently not assigned within the scope of your autoreleasepool it is also not released with with your autoreleasepool
Why are you using primitiveValueForKey and not a dynamic accessor?
The dynamic accessors are much more
efficient, and allow for compile-time
checking.
How about calling [pool drain] instead of [pool release]?
I managed to solve the problem by doing : [document.managedObjectContext processPendingChanges] right before draining the pool. However, I don't understand what pending changes would be there? Could someone enlighten me on that?
Your observation that processPendingChanges seems to solve the problem suggests to me that, as you import, the UndoManager for your NSManagedObjectContext is keeping track of all the changes you make as you do your bulk import.
What processPendingChanges is doing (as I understand it) is pushing changes stored in the managedObjectContext to the persistent store.
Try [[document managedObjectContext] setUndoManager:nil] (or create a new managedObjectContext for the import and set its undoManager to nil, if your document.managedObjectContext is the 'main' managedObjectContext and you don't want to turn off undo registration.
Related
I am calling a selector which I want to use to fire off a background process with the following
[self performSelectorInBackground:#selector(startSync) withObject:nil];
For an example, lets say startSync looks something like this
-(void)startSync {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// expensive background process
Sync *sync = [Sync new];
[sync performSync];
[sync release];
[pool release];
}
The really intensive processing is happening in "performSync" of the sync object. It's retrieving some XML, parsing it into an array, and inserting it into a MySQL database. The process itself seems to be working fine and the Analyzer isn't showing any leaks, but using the profiler and doing a baseline Heap Mark at the beginning before it runs and then again after it runs is showing about a 5mb gain. To the best of our knowledge (no pun intended) we are properly allocating and releasing objects in the performSync process.
The question is I am running this process in the background, if I am creating an AutoreleasePool for it, and releasing it at the end of the background process, shouldn't it dealloc everything related to the background process when it is over? I don't have a good understanding of why all of the allocated objects aren't getting destroyed.
The release will only happen at the end of the event loop
We were missing a close database statement each time we were doing a record insert, which was creating more connections and causing our problem. After doing so, our baseline heap mark was at 1.22mb and our ending heap mark was 1.22mb, exactly as I was expecting.
I'm currently profiling my app and coming across a few leaks. I've tried releasing objects all over the place where I think they are needed. Each release has crashed the app.
Here's one line that I think is the culprit:
NSDictionary *dicUserData = [NSDictionary dictionaryWithObject:self forKey:#"chapter"];
Just wondering the best way to deal with this. I'm having issues with other leaks too that are kind of similar. It's worth noting that self is a custom class [Dal_Chapter].
Do I need to implement copy or something, call that in the above line and do autorelease on that?
Thanks in advance.
Using convenience methods such as dictionaryWithObject provide an autoreleased instance of the dictionary object. Unless you're retaining it elsewhere this is not where your leak is.
I would check out the static analyser it should be able to point out your leaks for you.
That dictionary will retain self so you shouldn't have to worry about it.
Is the owner of self releasing it ?
Basicly you don't have to do anything whith your dictionnary, but if you want to take control of the memory you'll need to do this :
NSDictionary *dicUserData = [[NSDictionary alloc] initWithObjects:yourObject forKeys:key];
and int your dealloc method,
[dicUserDate release];
But normaly you just have nothing to do... Are you sure that your leak come from your dictionnary ?
always keep all variables release in dealloc method. is it not in proper place it may be crash .check this link click here
Hey, I've got a quick autorelease question. I understand basically how it works, but I was wondering if the following would create a memory leak.
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString* string = [[[NSString alloc] init] autorelease];
[[string retain] autorelease];
[pool drain];
Will the string be sent two release messages?
Think of the your interaction with the retain count of an object purely as a delta.
If you increase it by one, you need to decrease it by one for that object to potentially be released.
So -- yes -- you increased it by one twice and decreased it by one twice in that code. Two releases on drain will be the result.
That will not create a memory leak and you are correct, it will be sent two release messages from the auto release pool. As long as you have one release/autorelease for every alloc/retain/copy you should not be getting any leaks.
I have a problem with the memory management in Objective-C. Say I have a method that allocates an object and stores the reference to this object as a member of the class. If I run through the same function a second time, I need to release this first object before creating a new one to replace it. Supposing that the first line of the function is:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
This means that a different auto-release pool will be in place. The code to allocate the object is as follows:
if (m_object != nil)
[m_object release];
m_object = [[MyClass alloc] init];
[m_object retain];
The problem is that the program crashes when running the last line of the method:
[pool release];
What am I doing wrong ? How can I fix this ?
Regards
Alan
First get a general understanding of the objective c memory management. You are confusing a lot of different things here. For example you don't have to retain the m_object since alloc already sets up the retain count with 1. Also normally you dont release you AutoReleasePool when you release a object. Like I said look up the documentation for memory management (pretty good actually).
Autorelease pools handle objects that have been specifically autoreleased
Example:
[object autorelease];
You have to have at least one NSAutoreleasePool in your program in case some code attempts to autorelease an object. If this is your only NSAutoreleasePool then releasing the pool maybe causing your problems.
I am calling a function repeatedly with a loop, and the loop runs inside of a thread. The thread has an autorelease pool.
I have the following code inside that function:
NSXMLDocument* undoXML;
NSData* undoData = [NSData dataWithContentsOfFile:undoFilePath];
undoXML = [[NSXMLDocument alloc] initWithData:undoData options:NSXMLDocumentTidyXML error:&err];
NSData* undoData2;
undoData2 = [undoXML XMLData];
[undoData2 release];
[undoXML release];
I'm getting the following strange results:
My program is leaking memory every time this function is called by the loop.
When I add the following code to the function:
NSData* undoData3;
undoData3 = [undoXML XMLData];
[undoData3 release];
My program leaks even more memory than before.
I'm really confused and I badly need help figuring out what's going on. Maybe my autorelease pool isn't working correctly? Why is this happening?
Are you sure it is leaking? Or is it simply growing in size?
What does your loop look like and how is the autorelease pool integrated into it?
The autorelease pool must be inside the loop or your loop will just build up tons of memory over time. That the leaks instrument doesn't show leaks indicates that you have violated the memory management rules or your loop is incorrect.
Try running Instruments on your project w/ the leak detection settings. This should identify exactly where your leak is occurring (even in the system libraries).
Run -> Run With Performance Tool -> Leaks
undoData should be preset to be autoreleased (according to naming convention dataWithContentsOfFile: returns an autoreleased object). But unless you have your own autorelease pool, nothing that is set to autorelease will actually be deallocated until the active pool is drained (i.e. sometime after your function returns).
Your thread may have its own autorelease pool, but unless you are creating one inside your own function, nothing will be deallocated until after your function exits.
If you want to trigger the draining of autoreleased objects in the middle of a function (say once per loop), you need to manage your own autorelease pool.
while(looping) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do stuff that produces autoreleased objects
[pool drain];
}
Also, per cobbal's comment on your question, it looks like you should not be releasing undoData2 (or undoData3). Based on the naming convention -[NSXMLDocument XMLData] should be returning an autoreleased object.
If you have access to the source code of the NSData class you should look at what objects are being instantiated when undoData3 is created. I say this because you create the object and immediately destroy it. The issue must be that memory is being allocated inside the class but not being deallocated in it's destructor.