I have a function that returns an NSMutableArray of custom objects from a SQL query. The custom object basically holds the data for a database record. Whoever calls this function needs to retain the array, but that’s not the problem. The method loads the NSMutableArray in a loop iterating over the SQL results. The problem is that the Instruments application says it is leaking from the loaded NSStrings while getting the data from sqlite column results and the Record object holding it. I have tried even implementing my own NSAutoreleasePool for the NSStrings with no result (shown). I have also tried using a convenience method (stringWithUTF8String) instead (not shown) so I would not need to release the NSStrings and it did not work. When I comment out the part for the addObject in the NSMutableArray the memory leak is gone.
I know that NSMutableArray does a retain on the object (Record) when using addObject but I have a release then after. What is it? Here is snips of code:
Code:
/*** Record.h ******/
@interface Record : NSObject {
NSString *name;
NSString *title;
int age;
}
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *title;
@property int age;
@end
/**** Record.m ****/
#import "Record.h"
@implementation Record
@synthesize title;
@synthesize name;
@synthesize age;
@end
/******** Some other .m file ********/
-(NSMutableArray *) getQueryList{
int result = SQLITE_OK;
sqlite3_stmt *statement;
NSMutableArray *list = [[NSMutableArray alloc] init];
NSString *listSQL = [[NSString alloc] initWithFormat:
@"SELECT name,title,age FROM MyRecord"];
//Get Query
result = (sqlite3_prepare_v2(dbConnection,[listSQL UTF8String],
(int) -1, &statement, NULL));
[listSQL release];
if (result == SQLITE_OK){
NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW){
Record *myrecord = [[Record alloc] init];
// Name
NSString *strName = [[NSString alloc] initWithUTF8String:
(char *) sqlite3_column_text(statement,0)];
[myrecord setTitle:strName];
[strName autorelease];
// Title
NSString *strTitle = [[NSString alloc] initWithUTF8String:
(char *) sqlite3_column_text(statement,1)];
[myrecord setImageFilename:strTitle];
[strTitle autorelease];
// Age
[myrecord setAge:sqlite3_column_int(statement,2)];
/* Problem handling memory management */
[list addObject: myrecord]; // If comment out here no leak else leaks
[myrecord release];
[myPool drain];
}
[myPool release];
sqlite3_finalize(statement);
}
/* Return with autorelease, because who ever calls needs to retain */
return ([list autorelease]);
}
Last edited by rotjager; 10-16-2009 at 07:59 AM.
Reason: Formatting corrected
The problem is solved. I forgot after I get the list and retain it,
I forget to release it. The DatabaseWorks class has the getQueryList method
returning the NSMutableArray with autorelease. So the code below illustrates
So the method works either of the possible ways. You have to remember that after getting a NSMutableArray which you return with autorelease and must call retain, that you have to release it when done. That simple.
I knew as soon as I put this online for help I would find it myself, its always the case.
You have to remember that after getting a NSMutableArray which you return with autorelease and must call retain, that you have to release it when done. That simple.
dont think so.. this is enough.. right ?
Code:
dbObj = [[DatabaseWorks alloc] init];
NSMutableArray *myList = [[dbObj getQueryList] ];
.. use the list ..
[dbObj release];
__________________ lazy blogs
The Lord's holy name be praised.
Last edited by david_david; 10-17-2009 at 12:07 AM.