NSString *hostStr2 = [[NSString alloc] initWithFormat:#"http://%#/getplaylist.php?ip=%#",yourip,restip];
NSLog(#"XMLAppDelegate checkstatusthread call to php for status,playlist and nowplaying XML's %#" ,hostStr2);
NSData *dataURL2 =[NSData dataWithContentsOfURL: [ NSURL URLWithString: hostStr2 ]];
[hostStr2 release];
NSString *playlistdata=[[NSString alloc] initWithData:dataURL2 encoding:NSASCIIStringEncoding];
NSArray *ipItemsArray;
// memory leak showing at below line
ipItemsArray =[playlistdata componentsSeparatedByString:#"|^|"];
[playlistdata release];
What I am storing in ipItemsArray is a big XML data separated with a delimiter '|^|'.
The problem is when i run this it is giving memory leaks in this array.
Is there any other type of array that we can use or can someone better optimize this code so that i can get rid of the memory leaks happening.
better to allocate memory to that array.And release it in the dealloc a method
Related
I am working on JSON data parsing with lots of images downloading and data parsing.I have following code for parsing
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responseString = [[NSString alloc] initWithData:webdata encoding:NSASCIIStringEncoding];
[webdata release];
[connection release];
NSDictionary *values = [(NSDictionary*)[responseString JSONValue] objectForKey:#"UserId"];
NSDictionary *Active = [(NSDictionary*)[responseString JSONValue] objectForKey:#"Active"];
[responseString release];
NSString *UserID=[NSString stringWithFormat:#"%#",values];
NSString *Status=[NSString stringWithFormat:#"%#",Active];
[WSDelegate WServiceResponseMsg:#"WS_Authenticate_User" withResponse:UserID forParam:Status];
}
I have many classes with above code for parsing but app crashes after some time interval because of SBJSON parser.In instrument it gives app crashed because of low memory warning.
It is a very wrong assumption that most of the developers have while using SBJSONParser that, it has memory leaks. SBJSONParser does not has any leaks and does not introduces leaks in your code.
It is true that INSTRUMENTS tells you that the leak is because of SBJSONParser, but it denotes something else. Leaks are because of the way you have implemented SBJSONParser APIs. You must have done something wrong in your code.
Go to the leaks in your instruments. Open Extended Details toolbar and see the line of code that has leak. Instruments tells you the nearest place where the leak is.
Better option would be to use NSJSONSerialization that come as a part with iOS 5 and above
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSMutableDictionary *values = [NSJSONSerialization JSONObjectWithData:receivedData options:NSJSONReadingMutableContainers error:&error];
}
Finally got solution.Just use below line for JSON parsing.Remove NSMutableDictionary and use id :
NSError *jsonError = nil;
id allValues = [NSJSONSerialization JSONObjectWithData:webdata
options:0
error:&jsonError];
NSArray *array = [allValues objectForKey:#"Contestants"];
I am using following code to parse JSON and getting memory leak (100%) on line number 2. I don't know what is the problem, can someone help me ?
NSString *response = [request responseString];
NSMutableDictionary *responseJSON = [response JSONValue]; (100% leak)
NSString *tockenString = [responseJSON objectForKey:#"Token"];
NSString *userIDString = [responseJSON objectForKey:#"ID"];
I found the answer. Go to SBJsonParser.m function scanRestOfString and change the line
from
*o = [[NSMutableString alloc] initWithBytes:(char*)c length:len encoding:NSUTF8StringEncoding];
to
*o = [[[NSMutableString alloc] initWithBytes:(char*)c length:len encoding:NSUTF8StringEncoding] autorelease];
SBJsonParser has a like in scanRestOfString/NSMutableString. I reported the bug as well. Thank you all.
Remove those 2 autoreleases. They overrelease the objects.
I've had a similar problem but it turned out the leak was actually higher in the chain of methods, but Instruments was (mistakenly) pointing to this line. Look at the methods that store the results retrieved from this code.
i've been reading for hours, searched apple's doc, stackoverflow, can't understand what i'm doing wrong....
when i use this data from a XML plist on my UITableViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"arrayofstrings"
ofType:#"plist"];
NSData *myData = [NSData dataWithContentsOfFile:path];
NSString *error;
NSPropertyListFormat format;
myArray = [NSPropertyListSerialization propertyListFromData:myData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
}
my tableview shows the first visible rows just fine but crashes when trying to scroll.
it doesn't happen when instead of the XML data i use something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
myArray = [[NSArray alloc] initWithObjects:#"thing1", #"thing2", #"thing3", #"thing4", #"thing5",#"thing6", #"thing7", #"thing8", #"thing9", #"thing10",
#"thing11",#"thing12", #"thing13", #"thing14", nil];
}
this way the tableview scrolls just fine. what's my problem?! Is the plist conversion to array supposed to be in any other way?
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"arrayofstrings"
ofType:#"plist"];
NSData *myData = [NSData dataWithContentsOfFile:path];
NSString *error;
NSPropertyListFormat format;
myArray = [[NSPropertyListSerialization propertyListFromData:myData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error] retain];
}
The return value from propertyListFromData:mutabilityOption:format:errorDescription is autoreleased. Make sure you call retain so it doesn't get released out from under you at the end of the current run loop.
The second method works because creating the NSArray with alloc/init leaves the array with a retain count of 1.
The problem is that in the first case your call to [NSPropertyListSerialization propertyListFromData: returns an NSArray with no retain count on it (note the method doesn't have alloc, new, or copy in the name) - and then you don't retain this NSArray. Hence, the array is getting deallocated shortly after, and your code crashes trying to access garbage memory.
In the second case, you are making an NSArray using alloc - this returns an NSArray with a retain count of 1, which means it isn't deallocated (until a release gets called at some point).
To fix this, in your first case you want to assign the array as follows:
self.myArray = ...
The self. is the crucial part here (assuming you have declared the myArray property as retain).
There's plenty of resources and blog posts available concerning memory management.
In my app, I have a bunch of different image packs to download. The images are downloaded from my website one by one. The packs contain anywhere from 100-1500 images and each image is about 100KB-200KB.
When downloading the images, I have a method that selects the images to download, then I have a second method that does the actual downloading based on parameters sent from the main method. Here is the code for the download method:
-(BOOL) downloadImageName:(NSString *)imageName ImageGroup:(NSString *)imageGroup AndRow:(int)row {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSURL *downloadURL = [NSURL URLWithString:[NSString stringWithFormat:#"http://www.website.com/%#_0001.jpg",imageName]];
NSData *data = [NSData dataWithContentsOfURL:downloadURL];
NSString *savePath = [NSString stringWithFormat:#"%#/%#^%#_%#.jpg",docsPath,currentServerCycle,imageGroup,imageName];
BOOL downloaded = [data writeToFile:savePath atomically:YES];
if (downloaded)
return YES;
}
else {
return NO;
}
}
The problem I am having is this:
When I run this with performance tools looking at allocations I'm seeing that the app is keeping mallocs (NSConcreteData) each time an image is downloaded and only releasing them when the main method (the one calling this download method) completes. Thats fine for the smaller image packs, but the larger ones are obviously crashing after my total allocations hit something like 300+MB (the normal amount of allocations in my app is about 3mb).
They arent leaking, because once the image pack is downloaded and the method ends, all the mallocs are gone.
I have tried manually allocing and releasing the NSData *data but it has no effect.
Perhaps the autorelease pool the objects are in is not being drained until the main method returns. You might try adding NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; at the beginning of your download method, then [pool drain]; right before you return from the download method. You need to make sure you release the pool before you return no matter where you return otherwise you'll leak the pool.
Also, just as a point of standard Objective-C style, your method should be named:
(BOOL)downloadImageName:(NSString *)imageName imageGroup:(NSString *)imageGroup andRow:(int)row
with lowercase letters to start the "imageGroup:" and "andRow:" argument names.
I had the following code that takes in 14 mb or more of image data encoded in base4 string and converts them to jpeg before writing to a file in iphone. It crashes my program giving the following error :
Program received signal: “0”.
warning: check_safe_call: could not restore current frame
I tweak my program and it can process a few more images before the error appear again. My coding is as follows:
// parameters is an array where the fourth element contains a list of images in base64 >encoded string
NSMutableArray *imageStrList = (NSMutableArray*) [parameters objectAtIndex:5];
while (imageStrList.count != 0) {
NSString *imgString = [imageStrList objectAtIndex:0];
// Create a file name using my own Utility class
NSString *fileName = [Utility generateFileNName];
NSData *restoredImg = [NSData decodeWebSafeBase64ForString:imgString];
UIImage *img = [UIImage imageWithData: restoredImg];
NSData *imgJPEG = UIImageJPEGRepresentation(img, 0.4f);
[imgJPEG writeToFile:fileName atomically:YES];
[imageStrList removeObjectAtIndex:0];
}
I tried playing around with UIImageJPEGRepresentation and found out that the lower the value, the more image it can processed but this should not be the way. I am wondering if there is anyway to free up memory of the imageStrList immediately after processing each image so that it can be used by the next one in the line.
Your problem is that the UIImages and NSDatas are piling up in memory in a loop. Normally the autorelease pool would take care of this at the end of the event loop, but you're not letting it get that far. You have two choices:
Explicitly allocate/init and then release when done the UIImage and NSData objects, rather than using the +class methods.
Create an explicit autorelease pool inside the loop, and drain it at the end. Do this with:
NSAutoreleasePool * myPool = [[NSAutoreleasePool alloc] init];
[myPool release];
NSMutableArray *imageStrList = (NSMutableArray*) [parameters objectAtIndex:5];
while (imageStrList.count != 0) {
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
NSString *imgString = [imageStrList objectAtIndex:0];
// Create a file name using my own Utility class
NSString *fileName = [Utility generateFileNName];
NSData *restoredImg = [NSData decodeWebSafeBase64ForString:imgString];
UIImage *img = [UIImage imageWithData: restoredImg];
NSData *imgJPEG = UIImageJPEGRepresentation(img, 0.4f);
[imgJPEG writeToFile:fileName atomically:YES];
[imageStrList removeObjectAtIndex:0];
[pool release];
}
You should create another autoreleasepool inside the loop because objects created inside loop won't be released until the program get out from the loop.
Auto release pool inside the loop will release all objects created inside the loop every time.