Memory Leak in TouchMXL? - iphone

I'm using TouchXML to parse an XML-stream the following way:
CXMLDocument *parser = [[CXMLDocument alloc] initWithXMLString:responseString options:0 error:nil];
[responseString release];
// array holding all the nodes
NSArray *directionNodes = [parser nodesForXPath:#"//direction" error:nil];
NSArray *linieNodes = [parser nodesForXPath:#"//route" error:nil];
NSArray *timeNodes = [parser nodesForXPath:#"//time" error:nil];
for (int i = 0; i < [directionNodes count]; i++) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CXMLElement *direction = [directionNodes objectAtIndex:i];
CXMLElement *route = [linieNodes objectAtIndex:i];
CXMLElement *time = [timeNodes objectAtIndex:i];
// if rows are empty, stop it
if ([[direction stringValue] isEqualToString:#""]) {
break;
}
AbfahrtszeitResult *result = [[AbfahrtszeitResult alloc] init];
[result setLinie:[route stringValue]];
[result setZiel:[direction stringValue]];
[result setZeit:[time stringValue]];
[mutableAbfahrten addObject:result];
[result release];
[pool release];
}
Now, I always get a memory leak in the "stringValue"-line... am I doing something wrong or is it TouchXML?
Thanks a lot,
Stefan
-(NSString *) linie {
return linie;
}
- (void) setLinie:(NSString *)textValue {
[textValue retain];
[linie release];
linie = textValue;
}
-(NSString *) ziel {
return ziel;
}
-(void) setZiel:(NSString *)textValue {
[textValue retain];
[ziel release];
ziel = textValue;
}
-(NSString *) zeit {
return zeit;
}
-(void) setZeit:(NSString *)textValue {
[textValue retain];
[zeit release];
zeit = textValue;
}
+ (NSString *) cleanUpString:(NSString *) cleanme {
NSMutableString *tempString = [[NSMutableString alloc] initWithString:cleanme];
[tempString replaceOccurrencesOfString:#" " withString:#" " options:0 range:NSMakeRange(0, [tempString length])];
[tempString replaceOccurrencesOfString:#"&nbsp" withString:#" " options:0 range:NSMakeRange(0, [tempString length])];
return [tempString autorelease];
}

You have at least one leak when [[direction stringValue] isEqualToString:#""] is true as you break out of the for loop without releasing your AutoreleasePool. Beyond that, we'd need to see the implementation of your AbfahrtszeitResult class to see how your Linie setter is defined.

Related

CoreData inserting very huge DB exc_bad_access

I have ~60000 values in my DB.
I must to keep them all. But while inserting values I get exc_bad_access.
Here is my code:
if (context == nil)
{
context = [(radioAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", context);
}
[self performSelectorOnMainThread:#selector(deleteAllFromDB) withObject:nil waitUntilDone:YES];
// here is JSON parsing
int i=0;
#synchronized(self)
{
NSLog(#"Start");
NSEntityDescription *entity = [[NSEntityDescription entityForName:#"Station" inManagedObjectContext:context] autorelease];
for (NSString*string in stations)
{
if (![string isEqualToString:#""])
{
Station*station = [[[Station alloc] initWithEntity:entity insertIntoManagedObjectContext:nil] retain];
NSError *err = nil;
id parsedData = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers error:&err];
if (err) {
NSLog(#"error is %#", [err localizedDescription]);
}
[station setName:[parsedData objectForKey:#"nm"]];
[station setBit: [parsedData objectForKey:#"btr"]];
[station setEnabled: [NSNumber numberWithInt:1]];
//encoding id of the station
scanner = [NSScanner scannerWithString:[parsedData objectForKey:#"id"]];
[scanner scanHexInt:&tempInt];
NSNumber *numb = [[NSNumber alloc]initWithInt:i];
[station setNumber: [NSNumber numberWithInt:[numb intValue]]];
//encoding country ID
numb = [NSNumber numberWithInt:i];
[station setCountryID: [NSNumber numberWithInt:[numb intValue]]];
//encoding genre ID
numb = [NSNumber numberWithInt:i];
[station setGenerID:[NSNumber numberWithInt:[numb intValue]]];
[station setOrder:[NSNumber numberWithInt:i]];
[context insertObject:station];
float k = [stations count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
i++;
[scanner release];
[numb release];
[station release];
[parsedData release];
}
}
[context save:nil];
[entity release];
NSLog(#"Stop");
NSEntityDescription *entityGen = [NSEntityDescription entityForName:#"Genre" inManagedObjectContext:context];
NSURL* urlForGenre = [NSURL URLWithString:#"xxx.xxx"];
NSData *genres = [[NSData alloc] initWithContentsOfURL:urlForGenre];
NSError *err = nil;
NSArray *parsedGenres = [NSJSONSerialization JSONObjectWithData:genres options:NSJSONReadingMutableContainers error:&err];
if (err)
{
NSLog(#"error is %#", [err localizedDescription]);
}
for (int i =0; i<parsedGenres.count; i++)
{
Genre*gen = [[Genre alloc] initWithEntity:entityGen insertIntoManagedObjectContext:nil];
gen.name = [[parsedGenres objectAtIndex:i] objectForKey:#"nm"];
int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedGenres objectAtIndex:i] objectForKey:#"id"]];
[scanner scanInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
gen.number = [NSNumber numberWithInt:[numb integerValue]];
float k = [parsedGenres count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
[context insertObject:gen];
[gen release];
}
[entityGen release];
[context save:nil];
NSEntityDescription *entityCon = [NSEntityDescription entityForName:#"Country" inManagedObjectContext:context];
NSURL* urlForCoun = [NSURL URLWithString:#"yyy.yyy"];
NSData *countr = [[NSData alloc] initWithContentsOfURL:urlForCoun];
err = nil;
NSArray *parsedCountr = [NSJSONSerialization JSONObjectWithData:countr options:NSJSONReadingMutableContainers error:&err];
if (err)
{
NSLog(#"error is %#", [err localizedDescription]);
}
NSMutableArray* temp = [[NSMutableArray alloc] init];
for (int i =0; i<parsedCountr.count; i++)
{
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
countr.name = [[parsedCountr objectAtIndex:i] objectForKey:#"nm"];
int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedCountr objectAtIndex:i] objectForKey:#"id"]];
[scanner scanInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
countr.number = [NSNumber numberWithInt:[numb integerValue]];
[temp addObject:countr];
float k = [parsedCountr count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
[context insertObject:countr];
[countr release];
}
[context save:nil];
If my app doesn't crash, yes, it happens not by every launch. It crashes on:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
Please help! And sorry for my terrible English.
Update:
On:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
Thread 7: EXC_BAD_ACCESS (code=1, address=0x3f800008)
Other error is exc_bad_access too. But with code=2 and on other thread.
Update 2:
I enabled zombies mode in scheme of my debug. Nothing happened.
Update 3:
I think I have problems with memory.
GuardMalloc: Failed to VM allocate 4128 bytes
GuardMalloc: Explicitly trapping into debugger!!!
You can't pass nil as managedObjectContext parameter to initWithEntity:insertIntoManagedObjectContext: method. Try changing this:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
to this
// pass managed object context parameter
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:context];
Based on the documentation and my experience you can pass nil as managedObjectContext.
I was also getting an EXC_BAD_ACCESS and it came that the reason was that I was not retaining the managed object model(I was only creating a model to get the entity description and then it was released).
In particular, this is what I was doing:
In a test class, in the setUp method:
- (void)setUp
{
[super setUp];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *modelURL = [bundle URLForResource:#"TestDatamodel" withExtension:#"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
STAssertNotNil(model, nil);
_entity = [[model entitiesByName] objectForKey:NSStringFromClass([MyEntity class])];
STAssertNotNil(_entity, nil);
// ...
}
Then in a test method I was creating a managed object without a context like this:
NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:_entity insertIntoManagedObjectContext:nil];
And I was getting EXC_BAD_ACCESS here.
The solution was to add an ivar to the test class to keep a reference to the managed object model.

Memory leak while parsing XML using TouchXML

I am using TouchXML to parse XML. While i am running the same in "Profile" Mode. I can able to see the memory leak. How can I fix this issue?
-(NSMutableArray *) grabXML:(NSData *)xmlData andQuery:(NSString *)query {
NSMutableArray *blogEntries = [[[NSMutableArray alloc] init] autorelease];
CXMLDocument *rssParser = [[[CXMLDocument alloc] initWithData:xmlData options:0 error:nil] autorelease];
NSArray *resultNodes = [rssParser nodesForXPath:query error:nil];
for (CXMLElement *resultElement in resultNodes) {
NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];
int counter;
for(counter = 0; counter < [resultElement childCount]; counter++) {
[blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
}
for( int i = 0; i < [[resultElement attributes] count]; i++) {
CXMLNode *node = [[resultElement attributes] objectAtIndex:i];
[blogItem setObject:[[resultElement attributeForName:[node name]] stringValue] forKey:[node name]];
}
[blogEntries addObject:[blogItem copy]];
[blogItem release];
}
return [blogEntries copy];
}
I am calling the above method in the below mentioned format.
NSMutableArray *arr = [[self grabXML:responseData andQuery:#"//wsCheneliereResult"] autorelease];
[blogEntries addObject:[blogItem copy]];
Here is your mistake : you do not need to copy the blogItem, addObject: will actually retain its argument so that you can safely call [blogItem release]; afterward.
And you most probably should not do return [blogEntries copy] either, and return just blogEntries : this is common programming habit that methods whose name does not contain 'copy' or 'create' return autoreleased values, such as you do not need to release them when you are done with them.
To sum up, I would go with :
-(NSMutableArray *) grabXML:(NSData *)xmlData andQuery:(NSString *)query {
NSMutableArray *blogEntries = [[[NSMutableArray alloc] init] autorelease];
CXMLDocument *rssParser = [[[CXMLDocument alloc] initWithData:xmlData options:0 error:nil] autorelease];
NSArray *resultNodes = [rssParser nodesForXPath:query error:nil];
for (CXMLElement *resultElement in resultNodes) {
NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];
int counter;
for(counter = 0; counter < [resultElement childCount]; counter++) {
[blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
}
for( int i = 0; i < [[resultElement attributes] count]; i++) {
CXMLNode *node = [[resultElement attributes] objectAtIndex:i];
[blogItem setObject:[[resultElement attributeForName:[node name]] stringValue] forKey:[node name]];
}
[blogEntries addObject:blogItem];
[blogItem release];
}
return blogEntries;
}
and
NSMutableArray *arr = [self grabXML:responseData andQuery:#"//wsCheneliereResult"];

My app crashes with "Program received EXC_BAD_ACCESS" error iphone

When my app launches from BACKGROUND , I am running a new thread to get AddresssBook data using notification center. Here is my code which shows how I call the method
-(void)appLaunchedFromBackground:(NSNotification *) notification {
// NSThread *backgroundThread; is my ivar
backgroundThread = [[NSThread alloc]initWithTarget:self selector:#selector(getUpdatedAddressBookData) object:nil];
[backgroundThread start];
}
-(void)getUpdatedAddressBookData {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AddressBook *addBook = [[AddressBook alloc]init];
[addBook fetchAddressBookDataInBackground];
[addBook release];
[pool drain];
}
Here is my code for fetchAddressBookDataInBackground method
-(void)fetchAddressBookDataInBackground {
if (self.tempArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.tempArray = temp;
[temp release];
}
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *tempPeople = [[NSArray alloc]init];
tempPeople = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
APP_DELGATE.people = [NSArray arrayWithArray:tempPeople];
int peoCount = [APP_DELGATE.people count];
for (int i=0; i<peoCount; i++) {
ABRecordRef record = [APP_DELGATE.people objectAtIndex:i];
NSNumber *recordId = [NSNumber numberWithInteger:ABRecordGetRecordID(record)];
// Get fname, lname, company
NSString *fnm = (NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty) ;
NSString *lnm = (NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty) ;
NSString *comp = (NSString*)ABRecordCopyValue(record,kABPersonOrganizationProperty);
// Get Ph no
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(record, kABPersonPhoneProperty);
NSArray *tempPhNos = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
NSArray* phoneNumbers = [self getPhoneNoWithoutSymbols:tempPhNos];
NSString *strPhoneNos = [self getStringRepresentaionFromArray:phoneNumbers];
// Get emails
ABMultiValueRef emailProperty = ABRecordCopyValue(record, kABPersonEmailProperty);
NSArray* emails = (NSArray*)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSString *strEmails = [self getStringRepresentaionFromArray:emails];
// Get URL
ABMultiValueRef urlProperty = ABRecordCopyValue(record, kABPersonURLProperty);
NSArray* urls = (NSArray*)ABMultiValueCopyArrayOfAllValues(urlProperty);
NSString *strURLs = [self getStringRepresentaionFromArray:urls];
// Get Address
ABMultiValueRef address=ABRecordCopyValue(record, kABPersonAddressProperty);
CFDictionaryRef dic=nil;
NSMutableArray *addressArray = [[NSMutableArray alloc]init];
for (int index=0; index<ABMultiValueGetCount(address); index++) {
dic=ABMultiValueCopyValueAtIndex(address, index);
NSString* labelName=(NSString*)ABMultiValueCopyLabelAtIndex(address, index);
if (labelName) {
NSString *street =(NSString*) CFDictionaryGetValue(dic, kABPersonAddressStreetKey);
NSString *city= (NSString*)CFDictionaryGetValue(dic, kABPersonAddressCityKey) ;
NSString *state= CFDictionaryGetValue(dic, kABPersonAddressStateKey);
NSString *country=CFDictionaryGetValue(dic, kABPersonAddressCountryKey);
NSString *zipcode=CFDictionaryGetValue(dic, kABPersonAddressZIPKey);
NSString *addressDetails=#"";
if (street) {
addressDetails=[NSString stringWithFormat:#"%# ",street];
}
if (city) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,city];
}
if (state) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,state];
}
if (country) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,country];
}
if (zipcode) {
addressDetails=[NSString stringWithFormat:#"%# %# ",addressDetails,zipcode];
}
[addressArray addObject:addressDetails];
}
[labelName release];
CFRelease(dic);
}
NSString *strAddress = [self getStringRepresentaionFromArray:addressArray];
// Get Notes
NSString *noteString=(NSString *)ABRecordCopyValue(record, kABPersonNoteProperty);
// Get Birthdate
NSDate *birthDate=(NSDate*)ABRecordCopyValue(record, kABPersonBirthdayProperty) ;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM dd yyyy"];
NSString *birthdateString = [formatter stringFromDate:birthDate];
[formatter release];
// Get user image
UIImage *image = nil;
if( ABPersonHasImageData( record ) ) {
NSData *imageData = (NSData*)ABPersonCopyImageData(record);
image = [UIImage imageWithData:imageData];
[imageData release];
}
NSString *fullName = [NSString stringWithFormat:#"%# %#",fnm,lnm];
// Create User object & add it to array
User *user = [[User alloc]initUserWithUniqID:recordId.intValue FirstName:fnm lastName:lnm compositeName:fullName company:comp phoneNumbers:strPhoneNos emails:strEmails urls:strURLs address:strAddress notes:noteString dob:birthdateString userImage:image];
[self.tempArray addObject:user];
CFRelease(phoneNumberProperty);
[tempPhNos release];
CFRelease(emailProperty);
[emails release];
CFRelease(urlProperty);
[urls release];
CFRelease(address);
[addressArray release];
[birthDate release];
[comp release];
[noteString release];
[lnm release];
[fnm release];
[user release];
}
[tempPeople release];
CFRelease(addressBook);
addressBook = nil;
self.tempArray = [NSMutableArray arrayWithArray:[self.tempArray sortedArrayUsingSelector:#selector(compare:)]];
APP_DELGATE.allUsersArray = self.tempArray;
NSDictionary *dic = [NSDictionary dictionaryWithObject:self.tempArray forKey:BATCH_DONE_KEY];
[[NSNotificationCenter defaultCenter] postNotificationName:BACKGROUND_WORK_DONE_NOTIFICATION object:self userInfo:dic];
}
-(NSMutableArray*)getPhoneNoWithoutSymbols:(NSArray*)array {
if (self.phNoArray == nil) {
NSMutableArray *temp = [[NSMutableArray alloc]init];
self.phNoArray = temp;
[temp release];
}
[self.phNoArray removeAllObjects];
for (NSString *str in array) {
[self.phNoArray addObject:[self getPhNo:str]];
}
return self.phNoArray;
}
-(NSString*)getPhNo:(NSString*)str {
NSString *str0 = [str stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *str1 = [str0 stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *str2 = [str1 stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *str3 = [str2 stringByReplacingOccurrencesOfString:#"-" withString:#""];
return str3;
}
-(NSString*)getStringRepresentaionFromArray:(NSArray*)array {
return [array componentsJoinedByString:DELIMITER_SYMBOL];
}
But my app crashes with "Program received EXC_BAD_ACCESS" error at any line where I am using "ABRecordCopyValue" function . What I am missing? I am not getting whats wrong in my code?
I tried setting NSZombieEnabled = YES , but its not showing any message. Just saying "Program received EXC_BAD_ACCESS" at any line using ABRecordCopyValue function & in console I see (gdb) thats it.
Any knid of help is highly appreciated. Thanks.

Memory leak in NSMutableArray, NSArray, NSString in iPhone SDK

In my app, I got Memory leaks in NSMutableArray, NSArray and NSString.
Here is the code.
NSString *subQuery = [NSString stringWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];
[subArray addObjectsFromArray:subArray1];
NSString *columnQuery = [NSString stringWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];
[langArray addObjectsFromArray:newArray];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:[NSString stringWithFormat:#"%#",lblshortName.text]];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[tempArray addObject:[NSString stringWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
}
else {
[tempArray addObject:#"<empty>"];
}
NSString *detail = #"_________________";
for (int j=0; j<[lableNameArray count]; j++) {
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:[NSString stringWithFormat:#"%#",[lableNameArray objectAtIndex:j]]];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
detail = [NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4];
}
}
[detailTextArray addObject:detail];
}
When I run in Instruments I got leaks in
-subArray1 in second line.
-detail (NSString) in second for loop.
And subArray and langArray are my global arrays.
If I remove mutableCopy from NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; and NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; then subArray and langArray doesnot retain values.
How to avoid memory leak in this code?
Olease try this one, in above code you are creating two many objects that belong to autorelease pool here is one version where I tried to handle release of those string variables.
Second this is that the leak of detail is because you are de-referencing it many times in your code. And for subArray1 please see the comment
NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
// please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
[subArray addObjectsFromArray:subArray1];
[subQuery release];
NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
[langArray addObjectsFromArray:newArray];
[columnQuery relese];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:#"%#",lblshortName.text]];
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
[tempKey release];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
[tempArray addObject:tempString];
[tempString release];
}
else {
[tempArray addObject:#"<empty>"];
}
NSMutableString *detail = nil;
for (int j=0; j<[lableNameArray count]; j++)
{
detail = [[ NSMutableString alloc]initWithString:#"_________________"];
NSMutableString *key = [[NSMutableString alloc]initWithFormat:#"%#",[lableNameArray objectAtIndex:j]];
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key];
[key release];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail setString:[NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
}
[detailTextArray addObject:detail];
[detail release];
}
}
[subArray1 release];
[newArray release];
UPDATE : Please do read comments in the code and reply back so that things could be improved.
NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:#"SELECT %# FROM tbl_lang WHERE glossary = '%#'",append1,glossaryName];
//*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
[subArray addObjectsFromArray:subArray1];
[subQuery release];
NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:#"select AutoID,%# from tbl_lang where glossary='%#'",lblshortName.text,glossaryName];
//*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.
NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
[langArray addObjectsFromArray:newArray];
[columnQuery relese];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int i=0; i<[newArray count]; i++) {
NSMutableString *tempKey = [[NSMutableString alloc]initWithFormat:#"%#",lblshortName.text]];
NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
[tempKey release];
if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:#""] ) {
NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
NSMutableString *tempString = [[NSMutableString alloc] initWithFormat:#"%# : %#",lblshortName.text, decodedString3]];
[tempArray addObject:tempString];
[tempString release];
}
else {
[tempArray addObject:#"<empty>"];
}
NSMutableString *detail = [[ NSMutableString alloc]initWithString:#"_________________"];
for (int j=0; j<[lableNameArray count]; j++)
{
NSMutableString *key = [[NSMutableString alloc]initWithFormat:#"%#",[lableNameArray objectAtIndex:j]];
NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; //also here if you note you are using subArray1 not subArray?
[key release];
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail setString:[NSString stringWithFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
break;//I am not sure why you are checking this condition but assume that you want to get NOT NULL VALUE and add it to array?
}
}
[detailTextArray addObject:detail];
[detail release];
}
[subArray1 release];
[newArray release];
UPDATE 2:
if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
{
NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
[detail appendFormat:#"%#\n%# : %# ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
}
Thanks,
Not sure what is causing the memory leak, but this may help. This is a more direct way of copying the arrays, and may result in avoiding the leak:
NSArray *langArray =[[NSArray alloc] initWithArray: [self returnExecuteQuery:columnQuery] copyItems: YES];
This basically makes a one-level deep copy of the array returned by returnExecuteQuery. You can read about it in more detail in Collections Programming Topics.
I'm not sure how mutableCopy works and that may have something to do with the leak. If it copies the objects in the old array & then adds them to the new array, they may enter the array with a retain count of 2 (1 from the copy, and 1 from being added to an array.) It doesn't make much sense that it should work this way. But, if it does, that could account for the leak.
You could start by releasing your tempArray once done with it (after the loops).
Often, the higher levels leaks are hidden in the flood of lower level ones (ie a container leaking causes all its content to be leaked as well), which might be the case for your string.
Using mutableCopy] autorelease]; is fine by the way.

Memory Leak related

i am working on a fishing app these days and i am getting a memory leak problem
-(void)requestFinished:(ASIFormDataRequest *) request {
if(hud != nil){
[hud show:NO];
[hud release];
hud = nil;
}
isLoading = NO;
self.responseText = [request responseString];
[self parseXml]; //I am getting leak here
if ( [self.responseText hasPrefix:#"<result>"]) {
UIAlertView *info = [[[UIAlertView alloc] initWithTitle:#" " message:#"Limited Internet access, please find a stronger signal in the area" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]autorelease];
[info show];
}
if (!isRefreshButtonClicked) {
[UIAccelerometer sharedAccelerometer].delegate = self;
[NSThread detachNewThreadSelector:#selector(parseXml) toTarget:self withObject:nil];
} }
This is my function...
-(void) parseXml
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
_fishes = [[fishes parseXml:self.responseText] retain];
[self performSelectorOnMainThread:#selector(parseXmlDone) withObject:nil waitUntilDone:YES];
[pool release];
Here _fishes is an array which is getting a value from a array return type function.....and here is that function...
+(NSMutableArray *)parseXml:(NSString *)xmlString {
//xmlString = [xmlString stringByReplacingOccurrencesOfString:#"&" withString:#""];
const char *cString = [xmlString UTF8String];
NSMutableArray *fishes = [NSMutableArray array];
NSData *xmlData = [NSData dataWithBytes:cString length:strlen(cString)];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:&error];
if (doc == nil) { return nil; }
//parseXml
NSArray *_fishes = [doc.rootElement elementsForName:#"fishery"];
for (GDataXMLElement *_fish in _fishes) {
NSMutableDictionary *fish = [NSMutableDictionary dictionary];
NSArray *ids = [_fish elementsForName:#"id"];
if ([ids count]>0) {
GDataXMLElement *firstId = (GDataXMLElement *)[ids objectAtIndex:0];
[fish setValue:firstId.stringValue forKey:#"id"];
} else continue;
NSArray *names = [_fish elementsForName:#"name"];
if ([names count]>0) {
GDataXMLElement *firstName = (GDataXMLElement *)[names objectAtIndex:0];
[fish setValue:firstName.stringValue forKey:#"name"];...........
........
else continue;
NSArray *distances = [_fish elementsForName:#"distance"];
if ([distances count]>0) {
GDataXMLElement *distance = (GDataXMLElement *)[distances objectAtIndex:0];
[fish setValue:distance.stringValue forKey:#"distance"];
}else continue;
[fishes addObject:fish];
}
[doc release];
return fishes;
}
#end
I hope u guys will understand my problem...thanx
In -parseXml,
_fishes = [[fishes parseXml:self.responseText] retain];
will leak any previous object _fishes was pointing to in case -parseXml is sent more than once. You could use a retain property instead of an instance variable, or a setter method that releases the previous object, or release the previous object before assigning a new (retained) object to _fishes.