简体   繁体   中英

Ios memory management comes out so confused: CFGetRetainCount()

In ARC environment, I allocate a dynamic array of which each element is a pointer to NSObject*. Then use CFGetRetainCount to get the retain count of the NSObject. The result comes out as expected. However, when I change the NSObject to NSString, the retain count comes out as a large number, which confused me so much. I have searched google, but can't find any valuable information. So, can anyone explain? Appreciate any help.

first code snippet:

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;
}

second code snippet:

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;
}

the NSLog outputs confuse me: why the retain count is not "1" in the second code snippet? is there any different compared with the first code snippet?

The thing is that several Foundation classes in Objective C - like NSString , NSArray , NSNumber - don't behave like "normal" user classes. For example, NSNumber is typically a so-called tagged pointer - a pointer at a "illegal" address (which is not divisible by 4 or 8) and represents the value and not an address. NSString , NSArray ... are implemented as so-called class clusters, which is a mechanism that exchanges the internal implementation inside the initializer (eg returns a different object than the one that was allocated by the alloc call). Most often, NSString s are interned / atomized, which is a way to allow quick comparisons etc. by simple pointer comparision (instead of strncmp -like byte-by-byte comparisons).

To fall a long story short: You should never rely on retain counts, this is just an implementation detail of the reference counting mechanism.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM