2012-07-23 73 views
1

迈克·阿什说:__bridge_transfer的相关描述;它是否避免了双重保留?

当__bridge_transfer在铸造时,它告诉ARC这个对象已经保留,而ARC不需要再保留它。自从ARC获得所有权后,它在完成后仍会释放它。

锵文档说:

(__bridge_transfer T)运算连铸操作数,其必须具有非可保持指针类型,到目的地的类型,它必须是一个可保持对象指针类型。 ARC将在封闭的完整表达式的末尾释放该值,这取决于对本地值的通常优化。

没有在Clang文档中说它__bridge_transfer避免了双重保留。它只是表示该对象将在未来某个时间发布。

这是为什么?考虑以下代码片段:

NSString *value = (__bridge_transfer NSString *)CFPreferencesCopyAppValue(CFSTR("someKey"), CFSTR("com.company.someapp")); 

CFStringRef从retainCount +1开始。将其分配给值时,CFStringRef会再次被保留,因为默认情况下,会强烈引用value。这导致了双重保留。在范围的最后,一个-release被发送到value,但是没有其他任何东西可以平衡CFPreferences * 复制 * AppValue的滞留,从而导致内存泄漏。

__bridge_transfer如何避免双保留?

回答

1

Clang的文档与Mike Ash一致。它表示它执行强制转换,并且该对象在范围的末尾释放。在演员阵容中没有保留。

基本上,(__bridge_transfer T)导致价值被当作T类型的已经拥有的价值,只是如何调用[T new]将返回T类型的已经拥有的价值。

+0

Clang的文档并不会说“当__bridge_transfer用于演员时,它告诉ARC此对象已被保留,并且ARC不需要再保留它“。这意味着存在一些内置智能,ARC认识到我们即将分配给强引用类型,并随后吃掉-retain消息以避免双重保留。它是否正确? – 2012-07-23 21:42:40

+0

为了补充一点,是的,我同意在演员阵容上不会执行任何保留。但是在赋值为'value'时会出现保留。 – 2012-07-23 21:44:46

+0

@nessup:我应该澄清一下:Clang文档明确声明该值将在完整表达式的末尾释放。这基本上意味着“这是一个拥有的价值”。演员阵容中没有保留,但之后有一个释放。随后分配给局部变量将保留第二次,但当该变量超出范围时也会有第二次释放。优化器将识别双重保留并将其删除,因此您将剩下一个保留(并且在该范围末尾有一个单独的版本)。 – 2012-07-23 22:08:45

0

当你使用“transfer”时,ARC会在对象保留计数结束时递减对象 - 所以在这种情况下,你从1开始计数,“value”很强,所以它增加了计数,但是“传递” 导致的减量所以你最终回用1

NSString *value = (__bridge_transfer NSString *)CFStringCreateMutableCopy(NULL, 1000, CFSTR("Hello World")); 
NSLog(@"value retainCount %ld", CFGetRetainCount((__bridge CFTypeRef)value)); 
NSLog(@"Value = %@", value); 

2012-07-23 17:45:49.421 TimeTester [75918:F803]值retainCount 1 2012-07-23 17:45 :49.423 TimeTester [75918:f803] Value = Hello World

+0

您对实际发生的行为的描述绝对正确。那么,在我看来,Mike Ash的推荐实际上导致了内存泄漏,因为没有任何东西可以平衡来自CreateMutablyCopy的+1 ... – 2012-07-23 21:53:27

+1

检查出http://www.mikeash.com/pyblog/friday-qa-2011- 09-30-automatic-reference-counting.html。 “__bridge_transfer注解解决了这个问题”的Cmd + F。 – 2012-07-23 21:54:14