Objective c 叮当声:什么是;方法返回带有+;“0保留计数”;想告诉我吗?

Objective c 叮当声:什么是;方法返回带有+;“0保留计数”;想告诉我吗?,objective-c,cocoa,clang,clang-static-analyzer,Objective C,Cocoa,Clang,Clang Static Analyzer,在XCode 3.2中运行带有叮当声的静态分析时,我经常遇到以下两个警告: 方法返回保留计数为+0的Objective-C对象(非所有者引用) 调用方此时不拥有对象引用计数的错误递减 可能引发此警告的代码示例: UIButton* button = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame: CGRectMake(x, y, width, height)]; return button; 我假设以这种方式创建的按钮是

在XCode 3.2中运行带有叮当声的静态分析时,我经常遇到以下两个警告:

方法返回保留计数为+0的Objective-C对象(非所有者引用)

调用方此时不拥有对象引用计数的错误递减

可能引发此警告的代码示例:

UIButton* button = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame: CGRectMake(x, y, width, height)];
return button;
我假设以这种方式创建的按钮是自动释放的,就像使用便利工厂方法创建的任何其他NSObject一样。所以我返回它,调用方可以决定是否保留它。有什么问题吗

在归还之前,我是否有义务保留并自动归还该对象? 最重要的是,无论这个警告是针对什么,都可能是可怕的发布相关崩溃的原因吗

我现在意识到这似乎只发生在UIButtons上。这是因为它是一个类集群吗

编辑:下面截图显示了clang发出这些警告(警告以粗体显示)的最小情况。创建对象的语句(类型为:消息的
按钮)上标记了这两个警告

1 方法返回保留计数为+0的Objective-C对象(非所有者引用)

2 调用方此时不拥有对象引用计数的错误递减

    CGRectMake(0.0f, 0.0f, img.size.width, img.size.height)];
    bt setImage:img forState:UIControlStateNormal];
    return bt;
}

原因很可能是使用了发送类型为:
按钮和
initWithFrame:
消息
init*
方法执行的任务对于给定对象只能执行一次。创建对象的类方法也会初始化它们。代码的结果是重复初始化。相反,发送带有消息类型的
按钮,然后分配给
框架
属性。

好。。。。那代码毫无意义

buttonWithType:
返回已初始化的UIButton实例。您不应该对其调用
-initWithFrame:

调用
setFrame:

错误的代码使分析器感到困惑


第二,为什么要用第三方工具进行分析呢。如果您在SnowLeopard上使用Xcode 3.2(应该是——它是Xcode的一个比Leopard上的上一个版本好得多的版本),您可以“构建和分析”。所有分析结果都将与您的代码很好地内联显示。

包含此代码的方法名称是否以“new”作为前缀?Clang静态分析器遵循标准的Cocoa命名约定,并假设-newSomething方法将返回一个retain计数为1的实例。如果它看到一个自动释放的对象从这样的方法返回,它可能会显示您看到的警告。

Old,Old,question。我也有同样的问题。我认为现有的答案成功地解释了为什么代码是错误的,以及为什么分析器说“+0 retain count”。然而,似乎没有人解释为什么分析器说代码正在减少保留计数。我想我知道为什么了。这是因为如何允许init方法返回与您发送消息的对象不同的对象。他们将释放原始对象,分配一个新对象,然后返回它。分析器假设任何init方法都可以做这样的事情,尽管本例中的init方法可能没有。

是有道理的,我将遵循您的建议。但是,您的解释是如何反映在叮当声发出的警告消息中的呢?事实上,是否存在错误地减少保留计数的危险?我不能说我注意到了任何与此相关的bug(但这当然可能是因为它们刚刚从我的雷达下经过)。这需要比我更多的关于Clang和Objective-C内部的知识。如果让我猜的话,我会说“+0 retain count”指的是对类型为:
按钮的调用,而
init*:
消息应该只发送给拥有的对象,因此发送
initWithFrame:
会引发警告。转换时,
按钮的类型:
错误地减少了保留计数,因为
initwithFrame:
需要一个拥有的对象。outis:Close。
initWithFrame:
消息错误,但未考虑到任何分析仪警告。谢谢。我对outis的评论中的附加问题同样适用。“Analyzer Middle”(分析仪混乱)可能是对无效警告消息的一种解释。其次,我仍然主要使用XCode3.1,因为我仍然主要使用Leopard。分析工具会在叮当声的基础上为您提供额外的建议和警告(有些有用,有些可能不太有用)。我不确定分析仪是否混淆了<代码>按钮,其类型:
返回一个自动删除(+0保留计数)对象,这正是分析器所说的正在发生的事情。你不会说什么语句得到了标志4;我猜这是一条你没有给我们看的
发布
自动释放
消息。不,没有发布或自动释放消息。(如果有,我可能会经常遇到车祸。)为了在这里得到最好的答案,我尽我所能向大家展示所有可能相关的信息。请看原始问题中添加的最小示例。我仍然想知道的是,这段公认错误的代码是否真的会导致崩溃?当然——在已经初始化的对象上调用-init*的行为是未定义的。不,不会。请参阅上面添加的最小示例。
    CGRectMake(0.0f, 0.0f, img.size.width, img.size.height)];
    bt setImage:img forState:UIControlStateNormal];
    return bt;
}