views:

151

answers:

4

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?

+1  A: 

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

Pestilence
It reports no leaks.
Chetan
Weird question, but is your project enabling Objective C's garbage collection? Mac, iPhone, iPod, or iPad app?
Pestilence
If it reports no leaks, why do you say (in the original question) that it is leaking?
gary
A: 

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.

Trey Sargent
If NSData has leaks, all iPhones would implode.
Pestilence
+2  A: 

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.

bbum
A: 

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.

Chris Johnsen
He'd crash, if he double released, no? I still think he has garbage collection turned on.
Pestilence