2

I have been tracking down memory leaks in my iOS app and I keep coming back to the following code using the leaks instrument:

NSMutableArray *resultSet = [[NSMutableArray alloc] initWithCapacity:3];

NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];

FMResultSet *rs = [db executeQuery:query,equipmentID];
while ([rs next])
{
    [resultSet addObject: [rs resultDict]];
}
[rs close];
[innerPool release];

return [resultSet autorelease];

Is this the correct (in terms of memory management) usage of FMDB? Here is a screenshot of the leaks instrument:

leaks

Detailed Screenshot of the leak:

detail

Crake
  • 1,661
  • 1
  • 13
  • 30

2 Answers2

1

Yes, this is correct memory management. The [rs close]; line is technically unnecessary, because it will happen (if it hasn't already) when the FMResultSet is deallocated (as part of the pool draining). But putting it in there explicitly is fine.

Is it possible you're over-retaining the return array?

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • Thanks Dave, yes I am over-retaining the return array. Each item gets retained (via a synthesized setter) by a UITableView cell subclass. These are in a reusable queue, may be something I don't understand about how the queue works. [detail](https://lh6.googleusercontent.com/-ZbnV40_WTrg/TjhOQKjBB4I/AAAAAAAAMtU/1tIUgWIT_MM/s800/leak2.jpg) See screenshot of the leak, the BaseCell setData method is the only one without a release. If I add [data release] to the dealloc on the basecell, I get a crash. Any ideas on why this would be crashing when it looks to be clearly retained via the setter? – Crake Aug 02 '11 at 19:26
  • 1
    The smoking gun turned out to be the following line: 'while ([rs next]) { result = [rs resultDict]; }' .... This was being called after the cell saved its data, and I believe that a direct assignment like this is a bad idea, I changed it to 'while ([rs next]) { result = [[rs resultDict] copy]; }' – Crake Aug 02 '11 at 20:40
  • At first I agreed with Crake about copying the dictionary, but it is not necessary since fmdb is already calling `copy`. – Sebastian Hojas Aug 03 '11 at 13:40
0

SQLite allocates and keeps a bunch of memory, which is only freed when the database is closed. You can also adjust how much memory it will allocate by issuing a 'pragma cache_size = nnn' command.

See this related question and answer:

memory leak (?) after sqlite+fmdb vacuum command

Community
  • 1
  • 1
TomSwift
  • 39,369
  • 12
  • 121
  • 149