开发者

NSString length and retainCount. Clarification needed

开发者 https://www.devze.com 2023-03-21 11:27 出处:网络
Based on the following code, please advise NSString *str= [[NSString alloc] initWithString:@\"Hello world\"];

Based on the following code, please advise

NSString *str= [[NSString alloc] initWithString:@"Hello world"];   

NSLog(@"Length: %lu\n", [str length]);              // 11
NSLog(@"Retain count is %lu\n", [str retainCount]); //1152921504606846975

[str release];

NSLog(@"%lu\n", [str length]);                  开发者_开发百科    // 11
NSLog(@"Retain count is %lu\n", [str retainCount]); //1152921504606846975
  1. Originally I was wondering why the number was so large but then saw a a post explaining it. Let me ask this instead ... Why does this number change greatly whether i use %d vs %lu. Originally, i used %d, but got a warning saying that "Conversion specified type int but the argument has the type NSUInteger (aka unsigned long). A fix was to change %d to %lu"

  2. Why doesn't the retain count decrement? Large number still shows up unchanged, after the str is sent release

  3. Why am i still able to access the str, after it was sent release?


This may be a hard answer to accept, but it's what you should do:

  1. Don't worry about it. (in terms of %d/%lu, those specifiers simply expect different data types, and %d (int) has a much smaller and different range from %lu (unsigned long))
  2. Don't worry about it.
  3. Don't do it, and especially don't rely on it.

It may be because you started with a constant string (@"Hello world") that the memory isn't being deallocated when you call release, and the retainCount is large. But if you have to care about the retainCount, you're doing it wrong.

You are releasing the string in the right place, and that's what matters — don't ever try to use it later.


ultimately, the behaviour is defined by the implementation of NSString -- just use retain/release properly in every case and you will be safe.

what's likely happening: NSString literals are immortal. you can write while (1) { [@"String" release]; } and there will be no issue.

the copy ctor you have called is likely returning a pointer to the string literal. in pseudocode:

- (id)initWithString:(NSString *)str
{
    self = [super init];
    if (self != nil) {
        if ([str _isStringLiteral] || [str _isImmutable]) {
            [self release];
            return [str retain];
        }
        ...
}

in this case, you are returned the pointer to the string literal, when passed through [[NSString alloc] initWithString:stringLiteral]. since sending release to the immortal string literal does nothing, you can see why it is still a valid object following what you could presume is a released object.

never rely on such details/optimizations, just use normal lifetimes and ref counting and you'll be fine.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号