Objective-C:在'self'未设置时使用的实例变量......但它是

时间:2013-07-22 21:56:51

标签: objective-c self

我的任务是清除代码库中的一些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或self] init ...]'的结果时使用的实例变量,并且attr的_buffer属性的解除引用被突出显示。

如果有帮助,警告似乎也提到在使用此方法调用时发现问题:

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

任何人都可以向我解释这里的缺陷究竟是什么?

TIA!

2 个答案:

答案 0 :(得分:4)

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

这样做:

_buffer = [[attr string] mutableCopy];

同样令人讨厌的attr->_attributes。显然,ZAttributedString exposes属性`作为私有头中的属性。


编译器警告似乎确实看起来非常乐观,完全具有误导性,而且很可能是错误的描述。提交一份错误以澄清这一点会很有用。


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

传入的attr可以是ZAttributedString实例或子类的实例,或者实际上是实现与ZAttributedString相同的接口的任何类的实例。因此,你真的必须通过访问者来保证你正在抓住正确的状态。

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

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

答案 1 :(得分:2)

您似乎看到了与此完全相同的错误:"[Bug 15092] New: static analyzer false positive: reports instance variable used while 'self' is not set to the result of [(super or self)] init"。它有一个非常相似的代码来重现bug。

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

enter image description here

使用comment解决了错误:

  

这是固定在行李箱中,或至少大部分是固定的 - 还有一些优势   警告会触发的情况,但不是你的项目。

     

(戴夫,现在所有主要的分析仪工程师都在Apple工作,所以有   没有真正需要文件重复。不在Apple工作的LLVM人员不会   可以访问随Xcode一起提供的Apple Clang,而这个修复程序没有   Xcode 4.6。您还可以从中获取更新的检查器构建   http://clang-analyzer.llvm.org

正如您所看到的,错误已修复但仍存在于Xcode 4.6中。坚持下一个版本的Xcode,分析仪警告应该消失。