Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 10-16-2009, 02:20 AM   #1 (permalink)
James Redpath
 
Join Date: Oct 2009
Posts: 4
Unhappy NSMutableArray Leaks in Loop

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
rotjager is offline   Reply With Quote
Old 10-16-2009, 02:46 AM   #2 (permalink)
Registered Member
 
Join Date: Oct 2008
Posts: 370
Default

modify
Code:
// Name
			NSString *strName = [[NSString alloc] initWithUTF8String: 
						  (char *) sqlite3_column_text(statement,0)];
			[myrecord setTitle:strName];
			[strName release];
			
			// Title
			NSString *strTitle = [[NSString alloc] initWithUTF8String: 
						 (char *) sqlite3_column_text(statement,1)];
			[myrecord setImageFilename:strTitle];
			[strTitle release];
__________________
lazy blogs
The Lord's holy name be praised.
david_david is offline   Reply With Quote
Old 10-16-2009, 03:45 AM   #3 (permalink)
James Redpath
 
Join Date: Oct 2009
Posts: 4
Default Tried that but not working and tried other things too

Quote:
Originally Posted by david_david View Post
modify
Code:
// Name
			NSString *strName = [[NSString alloc] initWithUTF8String: 
						  (char *) sqlite3_column_text(statement,0)];
			[myrecord setTitle:strName];
			[strName release];
			
			// Title
			NSString *strTitle = [[NSString alloc] initWithUTF8String: 
						 (char *) sqlite3_column_text(statement,1)];
			[myrecord setImageFilename:strTitle];
			[strTitle release];

I have tried this above and have even tried these below. The problem leads to this NSMutableArray addObject method.


Code:
// Have tried this with alloc and release
NSString *str = [[NSString alloc] initWithUTF8String: 
				(char *) sqlite3_column_text(statement,1)];
[myrecord setTitle: str];


// Have tried this full memory management
char *rowTextData = (char *) sqlite3_column_text(statement,1);
NSString *str = [[NSString alloc] initWithUTF8String: (char *) rowTextData];
[myrecord setTitle: str];
[str release];
rowTextData = nil;


// Have tried this with NSString convenience method that autoreleases
NSString *str = [NSString stringWithUTF8String: (char *) sqlite3_column_text(statement,10)];
[myrecord setTitle: str];
rotjager is offline   Reply With Quote
Old 10-16-2009, 04:29 AM   #4 (permalink)
Registered Member
 
Join Date: Oct 2008
Posts: 370
Default

also check the code of Record.h and Record.m
__________________
lazy blogs
The Lord's holy name be praised.
david_david is offline   Reply With Quote
Old 10-16-2009, 08:01 AM   #5 (permalink)
James Redpath
 
Join Date: Oct 2009
Posts: 4
Default

Quote:
Originally Posted by david_david View Post
also check the code of Record.h and Record.m
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


dbObj = [[DatabaseWorks alloc] init];

NSMutableArray *myList = [[dbObj getQueryList] retain];

.. use the list ..

[myList release]; // I forgot to do this.

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.
rotjager is offline   Reply With Quote
Old 10-16-2009, 08:12 AM   #6 (permalink)
Registered Member
 
Join Date: Oct 2008
Posts: 370
Default

Quote:
Originally Posted by rotjager View Post
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.
david_david is offline   Reply With Quote
Reply

Bookmarks

Tags
leaks, nsmutablearray, sqlite3_column_text

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 257
17 members and 240 guests
2WeeksToGo, @sandris, AdamL, ADY, BrianSlick, Dani77, Dattee, GHuebner, headkaze, mer10, prchn4christ, smithdale87, Thompson22, timle8n1, Touchmint, vigu360
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 158,880
Threads: 89,228
Posts: 380,747
Top Poster: BrianSlick (7,129)
Welcome to our newest member, @sandris
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 12:52 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0