首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS10 __weak指针使retainCount +1

iOS10 __weak指针使retainCount +1
EN

Stack Overflow用户
提问于 2017-12-05 14:33:06
回答 1查看 191关注 0票数 1

当我使用__weak指针引用NSObject时,会显示意外的retainCount。

测试代码和结果如下图所示。

以下是代码:

代码语言:javascript
复制
    id obj1 = [[NSObject alloc] init];
    id __weak obj2 = obj1;
    NSLog(@"obj1: %ld", CFGetRetainCount((__bridge CFTypeRef)obj1));        // line 31
    NSLog(@"obj2: %ld", CFGetRetainCount((__bridge CFTypeRef)obj2));        // line 32
    NSLog(@"obj1 again: %ld", CFGetRetainCount((__bridge CFTypeRef)obj1));  // line 33

所以~我的困惑是,obj2 2的retainCount预期为1,为什么retainCount是2?

我从书中读到:autoreleasepool,指针将对象注册到__weak,因此保留计数+ 1。

然而,obj1和obj2引用相同的内存地址,在这种情况下,obj1 1的retainCount也应该变成2,但是,它仍然保留在1中。

我知道retainCount不可靠,但我很好奇这是怎么回事。(我的环境是Xcode 8.3.3,iOS 10.3)

非常感谢任何人能向初学者解释这一点:)

EN

回答 1

Stack Overflow用户

发布于 2017-12-05 16:31:36

保留计数的确切值通常是依赖于编译器、Objective语言运行库和任何其他相关库(如Foundation)的实现细节。但是,只要你不依赖于行为,你就有理由怀疑它为什么会这样表现。

要么你的书错了,要么你误解了它。使用__weak不会将对象放在自动发布池中。

下面是第32行正在发生的事情(使用@"obj2: %ld"格式字符串)。

要安全地将对象引用传递给函数或方法(如NSLog),它必须是一个强保存的引用。所以编译器在obj2上生成对obj2的调用。这个函数原子地增加对象的保留计数,并返回引用。因此,在将对象引用传递给NSLog之前,对象的保留计数从1到2。

然后,在NSLog返回后,编译器将生成对objc_release的调用。因此,第三个NSLog将保留计数从2降到1。

如果您想确定发生了什么,请查看编译器的汇编程序输出。您可以要求Xcode向您展示它:

以下是程序集的相关部分:

代码语言:javascript
复制
    .loc    2 0 9 discriminator 1   ## /Users/mayoff/TestProjects/test/test/main.m:0:9
    leaq    -32(%rbp), %rdi
    ##DEBUG_VALUE: obj2 <- [%RBP+-32]
    .loc    2 16 66 is_stmt 1       ## /Users/mayoff/TestProjects/test/test/main.m:16:66
    callq   _objc_loadWeakRetained
    movq    %rax, %rbx
Ltmp4:
    .loc    2 16 29 is_stmt 0       ## /Users/mayoff/TestProjects/test/test/main.m:16:29
    movq    %rbx, %rdi
    callq   _CFGetRetainCount
    movq    %rax, %rcx
Ltmp5:
Ltmp20:
## BB#3:
    ##DEBUG_VALUE: obj2 <- [%RBP+-32]
    ##DEBUG_VALUE: obj1 <- %R15
Ltmp6:
    .loc    2 16 9 discriminator 1  ## /Users/mayoff/TestProjects/test/test/main.m:16:9
    leaq    L__unnamed_cfstring_.4(%rip), %rdi
    xorl    %eax, %eax
    movq    %rcx, %rsi
    callq   _NSLog
Ltmp7:
Ltmp21:
## BB#4:
    ##DEBUG_VALUE: obj2 <- [%RBP+-32]
    ##DEBUG_VALUE: obj1 <- %R15
    .loc    2 16 9 discriminator 2  ## /Users/mayoff/TestProjects/test/test/main.m:16:9
    movq    %rbx, %rdi
    callq   *_objc_release@GOTPCREL(%rip)

第16行(在我的测试中)是使用obj2的。您可以在调用objc_loadWeakRetained之前看到对CFGetRetainCount的调用,在NSLog返回后看到对objc_release的调用。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47656074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档