【问题标题】:Memory Leak with Plist SerializationPlist 序列化的内存泄漏
【发布时间】:2011-04-02 10:14:12
【问题描述】:

请帮我解决这个内存泄漏问题。在泄漏工具中,它显示了一个泄漏:库 Foundation 负责框架:NSPropertyListSerialization 中的 NSCFString(32 字节)。我正在释放错误,但仍然存在泄漏。我错过了什么?非常感谢!

    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
    }

【问题讨论】:

  • 有各种各样的帖子说这是一个苹果错误,有人说使用 NSPropertyListSerialization options:format:error 和其他人说切换到 JSON 序列化,但我还没有找到一个很好的答案.
  • 我看到一个错误:你不应该在代码中使用[anError release];您不拥有对 anError 的引用。 propertyListFromData: 将在返回您的代码之前自动释放它。然而,这是一个 double-free 错误,而不是 leak。我在您发布的代码中没有看到任何泄漏。
  • 在调试器中,po 泄漏的字符串的值,看看它是否给你任何提示。
  • 尝试检查设备上的内存泄漏,一些 Apple 库在模拟器上有轻微泄漏。不要释放错误,它是一个自动释放对象。代码似乎是正确的。

标签: objective-c serialization memory-leaks property-list


【解决方案1】:

首先,确保您没有使用过时或过时的方法调用。根据您的应用配置(这由您决定),您可能正在使用过时的方法调用;来自 Apple 文档:

propertyListFromData:mutabilityOption:format:errorDescription:

此方法已过时,很快就会被弃用。 (已弃用。请改用propertyListWithData:options:format:error:。)

使用推荐的api调用后没有检测到内存泄漏...测试代码:

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);
}

【讨论】:

  • +1 用于注意到过时的方法,这确实可能是问题所在。但是,请删除 [error release] 行,非常感谢 ;)
  • propertyListWithData:options:format:error: 也确实有泄漏。
【解决方案2】:

声明plist = [NSPropertyListSerialization propertyListFromData:rawCourseArray mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&anError]; 创建一个自动释放对象。如果您的代码现在在一个单独的线程中运行,而@autoreleasepool {...} 没有明确分配自动释放池,则该对象将永远无法释放并且将成为泄漏。
因此,如果您的代码在单独的线程中运行,请确保您已设置自动释放池。

【讨论】:

    【解决方案3】:

    通过我们在 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);
        }
    

    【讨论】:

      【解决方案4】:

      没有泄漏。将其全部包装在 @autoreleasepool 中,以确保自动释放的所有内容都作为测试立即消失。

      THEN 摆脱由 anError 的 double free 引起的潜在崩溃: 它是自动释放的,您不必再次释放它!

      【讨论】:

        【解决方案5】:

        尝试以这种方式阅读您的 plist:

        NSDictionary *dTmp=[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"data" ofType:@"plist"]];
        
        
        self.myarray=[dTmp valueForKey:@"Objects"];
        

        【讨论】:

          猜你喜欢
          • 2012-05-22
          • 1970-01-01
          • 1970-01-01
          • 2011-02-22
          • 1970-01-01
          • 1970-01-01
          • 2019-10-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多