【问题标题】:Leak or Crash - difference between autorelease and release泄漏或崩溃 - 自动释放和释放之间的区别
【发布时间】:2023-03-28 05:27:01
【问题描述】:

我有一个理解问题。这个方法给出:

- (NSArray*)test {
 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
 NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
            length:[data length] 
             encoding:NSMacOSRomanStringEncoding];
 result = [result stringByAppendingString:@"something"];
 NSArray *arr = [NSArray arrayWithObject:result];
 //[result release];
 return arr;
}

如果我取消注释 release,应用程序会崩溃并说它无法访问已释放的对象。
通过不releaseing result 字符串 Instruments 会报告泄漏 (NSPlaceholderString)。

我可以在alloc 它的同一行上autorelease 它,这将解决问题(我目前正在我的应用程序中这样做)。

如果我理解正确stringByAppendingString: 应该创建一个自动释放的对象,以便可以释放“旧”结果。那么arrayWithObject: 方法应该将copy 对象放入一个数组中。所以我的想法是在将字符串复制到数组后释放它。

我的知识是否遗漏了什么或有什么问题?

【问题讨论】:

    标签: objective-c nsstring release nsdata autorelease


    【解决方案1】:

    让我们逐行浏览您的代码。

    - (NSArray*)test {
     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
    

    这将创建一个数据对象。你不拥有它,但它会在该方法的剩余时间内一直存在。到目前为止,一切顺利。

     NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
                                                 length:[data length] 
                                               encoding:NSMacOSRomanStringEncoding];
    

    这将创建一个您拥有的字符串对象。同样,这里没问题——我们只需要稍后发布它。

    result = [result stringByAppendingString:@"something"];
    

    您丢弃了对result 中的字符串对象的引用,并存储了一个您不拥有的新字符串对象。这是一个泄漏,因为您不能再释放原始字符串。另外,您注意到新字符串可以被视为自动释放对象是正确的——这意味着您不应该释放它。

    NSArray *arr = [NSArray arrayWithObject:result];
    

    与您的看法相反,这并没有复制任何内容。它只是保留对新字符串的引用并保留它。

    //[result release];
    

    此时你不应该释放result,因为它包含的对象不是你拥有的——你是从stringByAppendingString:获得的,而不是从newallocretaincopy 在它的名字中。释放这个不属于你的对象几乎肯定会在某个时候导致崩溃。您拥有并应该释放的旧对象在两行之前丢失了,并且释放其他东西来代替它也无济于事。

    【讨论】:

      【解决方案2】:
      result = [result stringByAppendingString:@"something"];
      

      这一行将第一个分配的字符串替换为一个新的自动释放字符串。

      所以第一个字符串被泄露,第二个字符串不应该被释放。这解释了为什么取消注释发布行会崩溃。

      【讨论】:

      • 这是正确的。你可以通过autorelease将初始分配给result来修复它。
      • @Seamus 我从来没有问过如何解决这个问题,我想要一个解释。我已经在我的问题中写了如何解决它,所以阅读 whole 问题,不仅示例代码很有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多