Memory Leak with Plist Serialization
Asked Answered
A

5

12

Please help me with this memory leak. In the leaks tool it shows a leak: NSCFString (32 bytes) in the library Foundation Responsible Frame: NSPropertyListSerialization. I am releasing the error but still a leak. What am I missing? Many thanks!

    NSPropertyListFormat format; 
    NSString *anError = nil;
    id plist;
    plist = [NSPropertyListSerialization propertyListFromData:rawCourseArray mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&anError];
    if (!plist){
          [anError release];
    } 
    NSArray *entries = (NSArray *)plist;
    for (NSDictionary *entry in entries) 
    {
      // DO SOMETHING
    }
Assemble answered 23/8, 2010 at 0:40 Comment(4)
There are various posts about this out there saying it's an apple bug, some say to use NSPropertyListSerialization options:format:error and others say switch to JSON serialization, but I haven't found a great answer yet.Shroyer
I see one bug: You shouldn't do [anError release] in your code; you don't own the reference to anError. propertyListFromData: will have autoreleased it before returning to your code. However, this is a double-free bug, not a leak. I don't see any leak in the code you posted.Improper
In the debugger, po the value of the string that's leaking to see if it gives you any hints.Clod
Try to check memory leaks on the device, some Apple libs have light leaks on simulator. Do not release the error, it is an autoreleasing object. The code seems to be right.Concent
D
1

First, make sure that you are not using deprecated or obsolete method calls. Depending on your app configuration (this is for you to decide) you may be using obsolete method calls; from Apple docs:

propertyListFromData:mutabilityOption:format:errorDescription:

This method is obsolete and will be deprecated soon. (Deprecated. Use propertyListWithData:options:format:error: instead.)

I did not detect a memory leak after using the recommended api call... Test Code:

NSArray *somearray = @[@"One",@"Two",@"Three"];
NSData *rawCourseArray = [NSKeyedArchiver archivedDataWithRootObject:somearray];

NSPropertyListFormat format;
NSError *anError = nil;
id plist;
plist = [NSPropertyListSerialization propertyListWithData:rawCourseArray options:NSPropertyListImmutable format:&format error:&anError];
if (!plist){
    [anError release];
}
NSArray *entries = (NSArray *)plist;
for (NSDictionary *entry in entries)
{
    // DO SOMETHING
    NSLog(@"%@",entry);
}
Dhow answered 5/2, 2013 at 4:7 Comment(2)
+1 For noticing the obsolete method, which really may be the problem. But, please remove the [error release] line, many thanks ;)Chatterjee
propertyListWithData:options:format:error: does have a leak as well.Hyperbolic
G
0

The statement plist = [NSPropertyListSerialization propertyListFromData:rawCourseArray mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&anError]; creates an autorelease object. If your code now runs in a separate thread to which no autorelease pool has been assigned explicitly by @autoreleasepool {...}, this object can never been released and will be a leak.
So, please ensure that you have set up an autorelease pool if your code runs in a separate thread.

Grovergroves answered 3/2, 2013 at 20:54 Comment(0)
A
0

Try this by we get dictionary in temp

    NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
    NSString *errorDesc = nil;
    NSPropertyListFormat format;
    NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
    if (!temp)
   {
        NSLog(@"Error reading plist: %@, format: %d", errorDesc, format);
    }
Ameliorate answered 4/4, 2013 at 11:55 Comment(0)
W
0

there is no leak. wrap it all in an @autoreleasepool to be sure everything that is autoreleased goes away right away as a test.

THEN get rid of that potential crash caused by the double free of anError: it is autoreleased and you don't have to release it again!

Writhen answered 29/4, 2013 at 7:58 Comment(0)
H
0

Try to read your plist in this manner:

NSDictionary *dTmp=[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"data" ofType:@"plist"]];


self.myarray=[dTmp valueForKey:@"Objects"];
Hypogenous answered 12/7, 2013 at 12:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.