非 ARC 项目中使用的 __strong 限定符

3
该项目未启用ARC,但我们错误地使用符合ARC的代码库,具体来说是使用GCDSingleton.h定义的一个用于创建单例对象的代码库:
#define DEFINE_SHARED_INSTANCE
+ (id)sharedInstance
{
  static dispatch_once_t pred = 0;
  __strong static id _sharedObject = nil;
  dispatch_once(&pred, ^{
    _sharedObject = ^{return [[self alloc] init];}();
  });
  return _sharedObject;
}

这似乎可以正常工作,即使共享对象使用了__strong限定符。我想知道为什么这不会导致错误或至少警告(最新的Xcode 4.6和iOS 6 SDK)。另外,由于该项目未启用ARC,如果有的话,__strong限定符到底是做什么的?
1个回答

5
在 MRC 代码中,__strong 被简单地忽略了。
我尝试编译一个简单的例子。
#import <Foundation/Foundation.h>

int main(int argc, char const *argv[]) {
    __strong NSString * foo = [[NSString alloc] initWithFormat:@"Hello, %s", argv[1]];
    NSLog(@"%@", foo);
}

使用ARC

clang -fobjc-arc test.m -S -emit-llvm -o arc.ir

没有自动引用计数(ARC)

clang -fno-objc-arc test.m -S -emit-llvm -o mrc.ir

需要进行llvm IR输出的比较。

以下是diff mrc.ir arc.ir的结果:

54a55,56
>   %17 = bitcast %0** %foo to i8**
>   call void @objc_storeStrong(i8** %17, i8* null) nounwind
63a66,67
> declare void @objc_storeStrong(i8**, i8*)
> 

基本上,ARC 和 MRC 之间唯一的区别在于添加了 objc_storeStrong 调用。


顺便提一下,没有 __strong 限定符的相同代码将产生完全相同的结果,因为 __strong 是 ARC 变量的默认限定符。


谢谢。这也是我所认为的 - 否则我会期望至少有编译错误或由于已释放对象而导致段错误。 - user2486931
为什么?你正在以一种有趣的方式分配(为什么要定义一个thunk并调用它?)一个具有+1保留计数的对象到永远不会超出范围的静态变量。没有崩溃,正如预期的那样。 - Gabriele Petronella
你误解了。我的意思是,如果它没有按预期工作,那么肯定有什么原因导致它没有被释放,但实际上并没有发生这种情况。无论如何,这里没有问题。 - user2486931

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接