__attribute__((NSObject)) 自动合成的 属性 没有在 dealloc 中释放
__attribute__((NSObject)) auto-synthesized property doesn't get released in dealloc
我想要一个由强引用支持但在 ARC 中具有 Core Foundation 对象类型(而不是 Objective-C 对象类型)的 属性。我相信这样做的正确方法是用 __attribute__((NSObject))
标记它,ARC 将像 Objective-C 对象类型 属性 一样管理它(即释放并保留分配,并释放时包含对象是 dealloc
ed):
@interface Foo : NSObject
@property (nonatomic, strong) __attribute__((NSObject)) CFArrayRef bar;
@end
@implementation Foo
// property bar is auto-synthesized
@end
(我知道 CFArray
是免费桥接到 NSArray
的。这只是为了举例。真正的用例是针对没有收费的 Core Foundation 类型-免桥接。)
但是当我将对象放入 Foo
对象的 bar
属性 并让 Foo
对象超出范围并得到 dealloc
ed,bar
中的对象被泄露,因为当 Foo
对象被释放时它没有被释放,就像使用常规 Objective-C 对象类型 属性:
void someFunc(void) {
Foo *foo = [[Foo alloc] init];
CFArrayRef arr = CFArrayCreateMutable(NULL, 42, &kCFTypeArrayCallBacks);
foo.bar = arr;
CFRelease(arr);
}
代码编译时没有任何警告或错误,并且顺利通过了分析。 Leaks 工具检测到可变数组已泄漏。
这是编译器错误吗?我使用的是最新的 Xcode (8.3.3).
ARC specification中有奇怪的写法,在定义retainable object pointer时,最后一种定义为:
typedefs marked with __attribute__((NSObject))
请注意,这使用 typdefs 而不是 declarations。该措辞在规范中再次使用了一点。这 almost 似乎建议您需要使用 typedef
来识别属性,这将是一个奇怪的设计。
不幸的是,当涉及到 属性 声明时,规范说(强调):
Applying __attribute__((NSObject))
to a property not of retainable object pointer type has the same behavior it does outside of ARC: it requires the property type to be some sort of pointer and permits the use of modifiers other than assign
. These modifiers only affect the synthesized getter and setter; direct accesses to the ivar (even if synthesized) still have primitive semantics, and the value in the ivar will not be automatically released during deallocation.
这似乎确实可以解释您所看到的行为 - 设计是半生不熟的,getter/setter 采用了语义但释放没有。
鉴于规范措辞,您对自动支持的一个希望似乎是首先为 CF 类型创建一个属性 typedef,然后在 属性 声明中使用它...如果为真则很奇怪,但它符合奇怪的措辞...抱歉目前无法检查,但我猜结果会令人失望。尝试将 nil
分配给 dealloc
中的 属性,因为它使用 setter(根据规范)具有正确的语义。
HTH
我想要一个由强引用支持但在 ARC 中具有 Core Foundation 对象类型(而不是 Objective-C 对象类型)的 属性。我相信这样做的正确方法是用 __attribute__((NSObject))
标记它,ARC 将像 Objective-C 对象类型 属性 一样管理它(即释放并保留分配,并释放时包含对象是 dealloc
ed):
@interface Foo : NSObject
@property (nonatomic, strong) __attribute__((NSObject)) CFArrayRef bar;
@end
@implementation Foo
// property bar is auto-synthesized
@end
(我知道 CFArray
是免费桥接到 NSArray
的。这只是为了举例。真正的用例是针对没有收费的 Core Foundation 类型-免桥接。)
但是当我将对象放入 Foo
对象的 bar
属性 并让 Foo
对象超出范围并得到 dealloc
ed,bar
中的对象被泄露,因为当 Foo
对象被释放时它没有被释放,就像使用常规 Objective-C 对象类型 属性:
void someFunc(void) {
Foo *foo = [[Foo alloc] init];
CFArrayRef arr = CFArrayCreateMutable(NULL, 42, &kCFTypeArrayCallBacks);
foo.bar = arr;
CFRelease(arr);
}
代码编译时没有任何警告或错误,并且顺利通过了分析。 Leaks 工具检测到可变数组已泄漏。
这是编译器错误吗?我使用的是最新的 Xcode (8.3.3).
ARC specification中有奇怪的写法,在定义retainable object pointer时,最后一种定义为:
typedefs marked with
__attribute__((NSObject))
请注意,这使用 typdefs 而不是 declarations。该措辞在规范中再次使用了一点。这 almost 似乎建议您需要使用 typedef
来识别属性,这将是一个奇怪的设计。
不幸的是,当涉及到 属性 声明时,规范说(强调):
Applying
__attribute__((NSObject))
to a property not of retainable object pointer type has the same behavior it does outside of ARC: it requires the property type to be some sort of pointer and permits the use of modifiers other thanassign
. These modifiers only affect the synthesized getter and setter; direct accesses to the ivar (even if synthesized) still have primitive semantics, and the value in the ivar will not be automatically released during deallocation.
这似乎确实可以解释您所看到的行为 - 设计是半生不熟的,getter/setter 采用了语义但释放没有。
鉴于规范措辞,您对自动支持的一个希望似乎是首先为 CF 类型创建一个属性 typedef,然后在 属性 声明中使用它...如果为真则很奇怪,但它符合奇怪的措辞...抱歉目前无法检查,但我猜结果会令人失望。尝试将 nil
分配给 dealloc
中的 属性,因为它使用 setter(根据规范)具有正确的语义。
HTH