根据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.h
和2.h
之间的区别吗?
更新0
Thx matt评论。
问题发生在GetTextLineGeometry
- 这个函数错误地执行了CFRelease(_str)
。现在我没有警告。
但我不明白为什么警告在_GetTextLineGeometry
而不是GetTextLineGeometry
?
答案 0 :(得分:1)
名称组件"创建"不执行任何魔法;这只是一个惯例问题。所以,就此而言,是"所有权的概念"。
所以忘记这一切,只考虑保留计数。
静态分析仪不仅仅是像你我这样的人类,它可以看到你所有的代码,而且可以算数。它正在计算此对象的保留和释放。当我们在你的第一个例子中到达CFRelease(_str)
时,你之前已经释放了这个相同的对象,导致其保留计数降至零;所以此时你正在执行过度发布。因此,静态分析器会在此时标记您。
现在让我们回过头来再看一遍"所有权"。只有"所有者"某事可以释放它;这就是"所有权"手段。但是静态分析仪非常愿意让你转让所有权,如果你知道自己在做什么的话。所以,如果你想"取得所有权"通过在GetTextLineGeometry中发布,静态分析器可以解决这个问题。但是当我们到达CFRelease(_str)
时,那是第二个"所有者" - 那不是板球运动员。因此,静态分析器再次标记 here 。