Objective C:switch inside loop - 如何避免(潜在的)内存泄漏

Posted

技术标签:

【中文标题】Objective C:switch inside loop - 如何避免(潜在的)内存泄漏【英文标题】:Objective C: switch inside loop - how to avoid (potential) memory leak 【发布时间】:2012-05-14 08:22:44 【问题描述】:

我有一个 for 循环,在开始时声明一个 NSObject“值”,然后实际创建“值”内的 switch 语句。那么“值”可以是一个 NSNumber、一个 NSDate、一个 NSData、一个 NSString 或 nil。这是代码:

for (int i = 0; i < self.columnCount; i++) 
  NSObject *value;
  switch (mysql_fields[i].type) 
    case ...
      ...
    case MYSQL_TYPE_LONG:
      value = [[NSNumber alloc] initWithInt:atoi(row[i])];
      /* [value autorelease]; */  // 2)
      break;
    case MYSQL_TYPE_DECIMAL:
      NSString *decimal = [[NSString alloc] initWithCString:(char *)row[i] encoding:NSUTF8StringEncoding];
      value = [[NSDecimalNumber alloc] initWithString:decimal];
      /* [value autorelease]; */  // 2)
      [decimal release];
      break;
    case ...
      ...
   // end of switch
 end of for
Field *field = [[[Field alloc] initWithRecord:record] autorelease];
/* [value autorelease]; */  // 3)
[field setValue:value forKey:@"value"];
/* [value release]; */  // 4)

现在我不知道如何释放“价值”。这是我尝试过的以及相应的 Xcode 4“分析器”消息:

    没有发布 -> “潜在的泄漏” [value autorelease] 在每个 case 语句中的 alloc/init 之后 -> “对象发送自动释放太多次” [value autorelease] 直接在最后一次使用之前 -> “对象发送自动释放太多次” [value release] 在最后一次使用之后 -> “此时不由调用者拥有的对象的引用计数递减不正确”

【问题讨论】:

【参考方案1】:

仅在分配对象的地方添加自动释放,删除其余部分:

value = [[[NSNumber alloc] initWithInt:atoi(row[i])] autorelease];
// ....
value = [[[NSDecimalNumber alloc] initWithString:decimal] autorelease];

【讨论】:

这与案例2相同),在“分析器”中给我“对象发送自动释放次数过多”。【参考方案2】:

您在 for 循环内声明 value,因此您必须在切换后但在 for 循环内释放它。

for (int i = 0; i < self.columnCount; i++)

    NSObject *value;
    switch (mysql_fields[i].type)
    
        case ...
            ...
        case MYSQL_TYPE_LONG:
            value = [[NSNumber alloc] initWithInt:atoi(row[i])];
            break;
        case MYSQL_TYPE_DECIMAL:
            NSString *decimal = [[NSString alloc] initWithCString:(char *)row[i] encoding:NSUTF8StringEncoding];
            value = [[NSDecimalNumber alloc] initWithString:decimal];
            [decimal release];
            break;
        case ...
            ...
    
    Field *field = [[[Field alloc] initWithRecord:record] autorelease];
    [field setValue:value forKey:@"value"];
    [value release];

【讨论】:

这是第 4 种情况),在“分析器”中显示“此时调用者不拥有的对象的引用计数不正确递减”消息 在您的示例中,案例 4 在 for 循环之外。这是一个巨大的差异。 这是真的 - 但是在简化此问题的代码时,错误潜入了。很抱歉。 已解决:在其中一个案例语句中,我从 NSString 类方法创建了“值”,而不是像在所有其他案例语句中那样使用 alloc/init。由类方法创建的对象是“自动释放的”。

以上是关于Objective C:switch inside loop - 如何避免(潜在的)内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 中的 switch 语句和实例变量分配

Prolog递归永远循环

win10系统获取insider preview出现问题怎么办

Inside i++

如何彻底删除Visual Studio Code Insiders,包括扩展

针对 Objective-C 枚举的新 Swift 5 警告:如何摆脱它们?