核心基础:为什么 LLVM 分析器报告调用者不拥有使用 *Create* 函数创建的对象?
Core Foundation: why LLVM analyzer report that caller doesn't own object created with *Create* function?
根据 The Create Rule,我创建了自己的 "constructor" - CFStringCreateFromGoString
。它的名称中包含 "Create"。我希望如果我调用 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
谢谢马特的评论。
问题出在 GetTextLineGeometry
- 这个函数错误地执行了 CFRelease(_str)
。现在我没有警告。
但我不明白为什么警告在 _GetTextLineGeometry
而不是 GetTextLineGeometry
?
name 组件 "Create" 没有任何魔法;这只是约定俗成的问题。因此,就此而言,是 "ownership".
的概念
所以忘记所有这些,只考虑保留计数。
静态分析器不像你我这样的普通人,它可以看到你所有的代码,并且可以计数。它正在计算此对象的保留和释放。当我们在您的第一个示例中到达 CFRelease(_str)
时,您之前已经释放了同一个对象,导致其保留计数降至零;所以此时你正在执行过度释放。因此,此时静态分析器会标记您。
现在让我们回过头来,站在"ownership"的角度再想一想。只有某个东西的 "owner" 才能释放它;这就是 "ownership" 的意思。但是静态分析器非常愿意让您转让所有权,如果您知道自己在做什么的话。因此,如果您想通过在 GetTextLineGeometry 中发布来 "take ownership",那么使用静态分析器就可以了。但是当我们到达 CFRelease(_str)
时,那是 second "owner" — 而这不是板球。因此,静态分析器再次在此处.
标记您
根据 The Create Rule,我创建了自己的 "constructor" - CFStringCreateFromGoString
。它的名称中包含 "Create"。我希望如果我调用 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
谢谢马特的评论。
问题出在 GetTextLineGeometry
- 这个函数错误地执行了 CFRelease(_str)
。现在我没有警告。
但我不明白为什么警告在 _GetTextLineGeometry
而不是 GetTextLineGeometry
?
name 组件 "Create" 没有任何魔法;这只是约定俗成的问题。因此,就此而言,是 "ownership".
的概念所以忘记所有这些,只考虑保留计数。
静态分析器不像你我这样的普通人,它可以看到你所有的代码,并且可以计数。它正在计算此对象的保留和释放。当我们在您的第一个示例中到达 CFRelease(_str)
时,您之前已经释放了同一个对象,导致其保留计数降至零;所以此时你正在执行过度释放。因此,此时静态分析器会标记您。
现在让我们回过头来,站在"ownership"的角度再想一想。只有某个东西的 "owner" 才能释放它;这就是 "ownership" 的意思。但是静态分析器非常愿意让您转让所有权,如果您知道自己在做什么的话。因此,如果您想通过在 GetTextLineGeometry 中发布来 "take ownership",那么使用静态分析器就可以了。但是当我们到达 CFRelease(_str)
时,那是 second "owner" — 而这不是板球。因此,静态分析器再次在此处.