【问题标题】:Ios memory management comes out so confused: CFGetRetainCount()Ios 内存管理出来的时候很困惑:CFGetRetainCount()
【发布时间】:2017-07-29 05:10:41
【问题描述】:

在 ARC 环境中,我分配了一个动态数组,其中每个元素都是指向 NSObject* 的指针。然后使用 CFGetRetainCount 获取 NSObject 的保留计数。结果如预期的那样出来。但是,当我将 NSObject 更改为 NSString 时,保留计数显示为一个很大的数字,这让我非常困惑。我搜索了谷歌,但找不到任何有价值的信息。那么,谁能解释一下?感谢任何帮助。

第一个代码sn-p:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject* __strong *arr = nil;
        arr = (id __strong *)calloc(2, sizeof(id));
        *arr = [[NSObject alloc]init];
        *(arr + 1) = [[NSObject alloc]init];
        NSLog(@"--->retainCount:%lu -->%@", CFGetRetainCount((__bridge CFTypeRef)*arr), *arr);
        //output:--->retainCount:1 --><NSObject: 0x100103a00>
        *arr = nil;
        *(arr + 1) = nil;
        free(arr);
    }
    return 0;
}

第二个代码sn-p:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString* __strong *arr = nil;
        arr = (id __strong *)calloc(2, sizeof(id));
        *arr = [[NSString alloc]initWithString:@"str_01"];
        *(arr + 1) = [[NSString alloc]init];
        NSLog(@"--->retainCount:%lu \n-->%@", CFGetRetainCount((__bridge CFTypeRef)*arr), *arr);
        //output:--->retainCount:1152921504606846975 -->str_01
        *arr = nil;
        *(arr + 1) = nil;
        free(arr);
    }
    return 0;
}

NSLog 输出让我感到困惑: 为什么第二个代码 sn-p 中的保留计数不是“1”?和第一个代码sn-p相比有什么不同吗?

【问题讨论】:

  • NSString 在内存管理方面有很多优化。你的字符串可能实际上是一个标记的指针。
  • 但是当我将 NSString 更改为其他对象时,例如 NSArray,保留计数也是一个巨大的数字。
  • 其他对象也对它们的内存管理进行了优化。空 NSArray 的初始化程序可能返回一个单例实例。
  • NSObject 对于所有 Object 类型都是超级的,你的意思是 NSObject 没有优化?那是赔率。而保留计数为 1152921504606846975 的 NSString,为什么呢?背后是什么场景?
  • NSTaggedPointerString 从其retainCount 方法返回2^64。我认为你在桥接它时会丢失一些位,因为retainCount 返回一个无符号值,而CFGetRetainCount 返回一个有符号值,所以你最终得到了那个数字。

标签: ios memory-management automatic-ref-counting dynamic-arrays retaincount


【解决方案1】:

问题在于,Objective C 中的几个 Foundation 类——例如 NSStringNSArrayNSNumber——不像“普通”用户类。例如,NSNumber 通常是所谓的标记指针 - 指向“非法”地址(不能被 4 或 8 整除)的指针,它表示值而不是地址。 NSStringNSArray... 被实现为所谓的类簇,这是一种在初始化器内部交换内部实现的机制(例如,返回与 alloc 调用分配的对象不同的对象) .大多数情况下,NSStrings 是实习/原子化的,这是一种允许通过简单的指针比较(而不是 strncmp-like 逐字节比较)进行快速比较等的方法。

长话短说:您永远不应该依赖保留计数,这只是引用计数机制的一个实现细节。

【讨论】:

  • 有些对象位于可被 2 整除的地址,顺便说一句。
猜你喜欢
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 2016-09-12
  • 1970-01-01
  • 2014-11-06
  • 2021-09-16
  • 2012-05-24
  • 2012-02-09
相关资源
最近更新 更多