3

在 XCode 3.2 和Nikita Zhuk 的分析工具中使用 clang 运行静态分析我经常遇到这对警告:

方法返回一个具有 +0 保留计数的 Objective-C 对象(非拥有引用)

调用者此时不拥有对象引用计数的不正确递减

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

UIButton* button = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame: CGRectMake(x, y, width, height)];
return button;

我假设以这种方式创建的按钮是自动释放的,就像使用便利工厂方法创建的任何其他 NSObject 一样。所以我返回它,调用者可以决定是否保留它。那有什么问题?

我有义务在返回之前保留并自动释放对象吗?最重要的是,这个警告所警告的东西是否会成为可怕的发布相关崩溃的原因?

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

编辑:下面的片段显示了clang发出这些警告的最小情况(警告以粗体显示)。buttonWithType:这两个警告都在创建对象(消息)的语句上标记。

-(UIButton*) ztupidTezt:(UIImage*) img
{
  UIButton* bt = [[UIButton buttonWithType:UIButtonTypeCustom]initWithFrame:

1 方法返回一个具有 +0 保留计数的 Objective-C 对象(非拥有引用)

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

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

4 回答 4

12

嗯....那个代码没有意义。

buttonWithType:返回已初始化的 UIButton 的实例。你不应该打电话-initWithFrame:给它。

打电话setFrame:

糟糕的代码使分析器感到困惑。

其次,为什么要使用第三方工具进行分析。如果您在 Snow Leopard 上使用 Xcode 3.2(您应该是 - 它是 Xcode 的一个比 Leopard 上的最后一个版本好得多的版本),您可以只“构建和分析”。所有的分析结果都将很好地与您的代码一起呈现。

于 2009-10-02T15:43:01.330 回答
6

原因很可能是同时发送 abuttonWithType:initWithFrame:消息。init*方法执行对给定对象只应执行一次的任务。创建对象的类方法也会初始化它们。您的代码的结果是重复初始化。相反,发送buttonWithType消息,然后分配给frame属性。

于 2009-10-02T15:40:15.907 回答
3

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

于 2009-10-02T21:15:14.097 回答
0

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

于 2011-09-02T06:27:17.377 回答