6

我的任务是清理代码库中的一些 Clang 错误。我对 iPhone 开发和 Objective C 非常陌生,但发现大多数问题都是微不足道的……不过,当我确定这很尴尬时,这个问题让我很困惑。

从 ZAttributedString 类:

- (id)initWithAttributedString:(ZAttributedString *)attr {
    NSParameterAssert(attr != nil);
    if ((self = [super init])) {
        _buffer = [attr->_buffer mutableCopy];
        _attributes = [[NSMutableArray alloc] initWithArray:attr->_attributes copyItems:YES];
    }
    return self;
}

clang 警告是“使用的实例变量,而 'self' 未设置为 '[super or self] init...]' 的结果,并突出显示了 attr 的 _buffer 属性的取消引用。

如果它有帮助,警告似乎还提到从这个方法调用时发现了问题:

- (id)copyWithZone(NSZone *)zone {
    return [(ZAttributedString *)[ZAttributedString allocWithZone:zone] initWithAttributedString:self];
}

谁能向我解释一下这里的缺陷到底是什么?

蒂亚!

4

2 回答 2

4

不要->用于访问实例变量,尤其是当 ivar 来自其他对象时。

做这个:

_buffer = [[attr string] mutableCopy];

那个讨厌的也一样attr->_attributes。显然, ZAttributedString exposesattributes` 作为私有标头中的属性。


该编译器警告在最乐观的情况下似乎完全具有误导性,并且很可能在描述中完全错误。提交一个错误以澄清这一点会很有用。


请注意,@maddy 声称使用->直接在attr传递的字符串中访问实例变量,因为它的作用类似于复制构造函数,这是不正确的。

传入的attr可能是一个ZAttributedString实例或一个子类的实例,或者,实际上,是任何实现与 相同接口的类的实例ZAttributedString。因此,您确实必须通过访问器来保证您正在获取正确的状态。

现在,作为一个实现细节,ZAttributedString可能要求入站实例是 的非子类实例ZAttributedString,但它应该isMemberOfClass:用来断言该要求(并且请不要这样做)。

有时使用直接 ivar 访问从另一个对象中提取状态的唯一地方是在 的实现中copyWithZone:,但这是非常脆弱的,并且经常导致古怪的破坏行为。事实上,copyWithZone:(在各种 plist 兼容的值类之外)已经充满了脆弱性和许多许多错误的来源。

于 2013-07-22T22:27:44.233 回答
2

您似乎看到了与此完全相同的错误:“[错误 15092] 新:静态分析器误报:报告使用的实例变量,而 'self' 未设置为 [(super or self)] init 的结果”。它附加了一个非常相似的代码来重现该错误。

如果您在 Xcode 4.6.3 中运行该代码,您可以验证它是否给出了与您看到的相同的错误警告。

在此处输入图像描述

该错误已通过以下评论解决:

这在主干中是固定的,或者至少大部分是固定的——仍然有一些边缘情况会触发警告,但不是你的项目。

(Dave,目前所有主要的分析器工程师都在 Apple 工作,因此没有必要提交重复文件。不在 Apple 工作的 LLVM 人员无法访问 Xcode 附带的 Apple Clang,并且此修复没有使 Xcode 4.6。您还可以从 http://clang-analyzer.llvm.org获得更新的检查器构建)

如您所见,该错误已修复,但仍存在于 Xcode 4.6 中。等待 Xcode 的下一个版本,分析器警告应该消失了。

于 2013-07-23T14:23:54.023 回答