3

I am using FMDB in my project and I have profiled my project using Instrument for Memory leaks. I have found out many leaks in this function of FMResultSet class. The leaks are at this line:

return [NSString stringWithUTF8String:c];

Can anyone explain me why it's happening and solutions for it? Because it's causing a lot of leak instances.

Here's my code:

//this is how i query and get result
FMResultSet *queryResult = [db executeQuery:queryString withArgumentsInArray:args];
//populate array from result set
NSMutableArray *resultArray = [self populateFromDB:queryResult];


//code of populateFromDB method
- (NSMutableArray*)populateFromDB:(FMResultSet*)queryResult 
{
   NSMutableArray *resultArray = [[[NSMutableArray alloc]init] autorelease];
    while ([queryResult next])
    {
        //custom model class
        MModel *model = [[MModel alloc] init];
        model.property1 = [queryResult stringForColumn:@"column1"];
        model.property2 = [queryResult stringForColumn:@"column2"];

        [resultArray addObject:model];
        [model release];
    }
    return resultArray;
}


//init method of model class
- (id)init
{
    if (self == [super init]) 
    {    
        //nothing..
    }
    return self;
}


//dealloc method of model class
- (void)dealloc
{
    [super dealloc];
}


//code of stringForColumn method of FMResultSet
- (NSString*)stringForColumn:(NSString*)columnName 
{
    return [self stringForColumnIndex:[self columnIndexForName:columnName]];
}


//code of stringForColumnIndex method of FMResultSet
- (NSString*)stringForColumnIndex:(int)columnIdx 
{

    if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
    return nil;
    }

    const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);

    if (!c) {
        // null row.
        return nil;
    }
    return [NSString stringWithUTF8String:c];
} 

Any help would be appreciated. Thanks in advance

Salman Zaidi
  • 9,342
  • 12
  • 44
  • 61
  • Are you using ARC? If not you are probably not properly releasing the string returned from the function stringForColumnIndex. (ie: the problem isn't in the code you posted, it's in how you're using the string it returns.) – Nicholas Hart Jul 29 '13 at 20:59
  • Yes not using ARC, I'm returning the result of this string to a new string instance.. – Salman Zaidi Jul 30 '13 at 04:12
  • I don't think there's anything wrong with the code you've posted. There must be something wrong with how you're using the return value. You're probably retaining it somewhere and not releasing it. You should post more of your code that shows how you're using the value(s) returned from this method. – Nicholas Hart Jul 30 '13 at 04:30
  • No retain, No release.. release causing crash.. tried everything.. – Salman Zaidi Jul 30 '13 at 04:41
  • let me paste some more code here – Salman Zaidi Jul 30 '13 at 04:46
  • what happens to the leaks if you run the same code but don't assign the query result to property1 and property2? – TomSwift Jul 30 '13 at 05:13
  • doesn't make any difference.. – Salman Zaidi Jul 30 '13 at 05:38
  • The line `[MModel release];` looks odd - should this not be `[model release];`? Apologies if this is nonsense, it's so long since I've programmed without ARC I've probably forgotten how it all works. – Rob Glassey Jul 31 '13 at 11:01
  • it's [model release].. typo error here.. I have edited post.. – Salman Zaidi Jul 31 '13 at 11:12
  • By convention, stringForColumnIndex should not be returning a retained object (since it begin new/alloc/et al), and it does not appear to. So that is not the problem. But presumably something near the call to that is a problem. Have you run the Analyzer? – Hot Licks Jul 31 '13 at 11:21
  • My first guess would be that resultArray is being over-retained somewhere. – Hot Licks Jul 31 '13 at 11:23
  • Static Analyzer is not showing any possible leak around these calls.. However, Instruments is showing leaks.. the leaks increase dramatically whenever DB is accessed throughout the execution cycle.. – Salman Zaidi Jul 31 '13 at 11:26
  • the resultArray is handled very carefully.. it's been around 3 months, I am facing this problem.. :-( Is there a chance that it's a FMDB's leak?? – Salman Zaidi Jul 31 '13 at 11:30
  • I suspect it's possible to use FMDB incorrectly and get it to leak. But I doubt that there is a design problem with it. And the profiler results suggest that those strings are being leaked somehow. So I'd first look at all the places where the pointers to those strings are being copied. – Hot Licks Jul 31 '13 at 15:50
  • Where is `selectedImage` coming from, when you call `[resultArray addObject:selectedImage];`? – Nicholas Hart Aug 01 '13 at 15:30

1 Answers1

0

According to the SQLLite docs:

The memory space used to hold strings and BLOBs is freed automatically.

It could be that the C string c is leaking from the point of view of Instruments since SQLLite is opaquely managing the memory for that string. You can confirm that by checking the type of the object that is leaking. (Is it a malloc? or some sort of CFString object?)

Dany Joumaa
  • 2,030
  • 6
  • 30
  • 45