核心基础:为什么LLVM分析器报告调用者不拥有使用* Create *函数创建的对象?

时间:2018-06-06 23:11:06

标签: objective-c core-foundation

根据The Create Rule我创建了自己的"构造函数" - CFStringCreateFromGoString。它包含"创建"在它的名字。我希望如果我调用CFStringCreateFromGoString,那么我拥有返回的对象。

但根据LLVM静态分析器,这并不完全正确,在某些情况下我会收到警告Incorrect decrement of the reference count of an object that is not owned at this point by the caller - 请参阅1.h。在其他没有警告的情况下 - 请参阅2.h

来自common.h

CFStringRef CFStringCreateFromGoString(_GoString_ str) {
    return CFStringCreateWithBytes(NULL, (UInt8*)_GoStringPtr(str), (CFIndex)_GoStringLen(str), kCFStringEncodingUTF8, false);
}

来自1.h

CGRect _GetTextLineGeometry(CGContextRef context, _GoString_ str, CTFontRef font) {
    CFStringRef _str = CFStringCreateFromGoString(str);
    CGRect r = GetTextLineGeometry(context, _str, font); // no warning if I remove this line
    CFRelease(_str); // warning here
    return r;
}

来自2.h

CTFontRef _CreateFontFromFile(_GoString_ path, struct FontSpec spec) {
    CFStringRef _path = CFStringCreateFromGoString(path);
    CTFontRef r = CreateFontFromFile(_path, spec);
    CFRelease(_path); // no warning
    return r;
}

有人可以解释1.h2.h之间的区别吗?

更新0

Thx matt评论。 问题发生在GetTextLineGeometry - 这个函数错误地执行了CFRelease(_str)。现在我没有警告。 但我不明白为什么警告在_GetTextLineGeometry而不是GetTextLineGeometry

1 个答案:

答案 0 :(得分:1)

名称组件"创建"不执行任何魔法;这只是一个惯例问题。所以,就此而言,是"所有权的概念"。

所以忘记这一切,只考虑保留计数。

静态分析仪不仅仅是像你我这样的人类,它可以看到你所有的代码,而且可以算数。它正在计算此对象的保留和释放。当我们在你的第一个例子中到达CFRelease(_str)时,你之前已经释放了这个相同的对象,导致其保留计数降至零;所以此时你正在执行过度发布。因此,静态分析器会在此时标记您。

现在让我们回过头来再看一遍"所有权"。只有"所有者"某事可以释放它;这就是"所有权"手段。但是静态分析仪非常愿意让你转让所有权,如果你知道自己在做什么的话。所以,如果你想"取得所有权"通过在GetTextLineGeometry中发布,静态分析器可以解决这个问题。但是当我们到达CFRelease(_str)时,那是第二个"所有者" - 那不是板球运动员。因此,静态分析器再次标记 here